├── .gitignore ├── AUTHORS ├── COPYING ├── COPYING.GPLv3 ├── ChangeLog ├── HACKING.md ├── Makefile.am ├── NEWS ├── README.md ├── TODO.md ├── autogen.sh ├── configure.ac ├── data ├── Makefile.am ├── Readme.md └── man │ ├── Makefile.am │ └── tilda.1.in ├── docs ├── multi-monitor-setup.png └── multi-monitor-setup.xcf ├── images ├── tilda_appearance-16-9.png ├── tilda_colors-16-9.png ├── tilda_general-16-9.png ├── tilda_keybindings-16-9.png ├── tilda_terminal_with_search_bar.png └── tilda_title_and_command-16-9.png ├── po ├── LINGUAS ├── Makevars ├── POTFILES.in ├── README ├── bg.po ├── ca.po ├── cs.po ├── de.po ├── el.po ├── en_GB.po ├── es.po ├── fr.po ├── hr.po ├── hu.po ├── it.po ├── lt.po ├── nb.po ├── oc.po ├── pl.po ├── pt.po ├── pt_BR.po ├── ru.po ├── sk.po ├── sl.po ├── sv.po ├── tr.po ├── uk.po ├── zh_CN.po └── zh_TW.po ├── src ├── Makefile.am ├── configsys.c ├── configsys.h ├── debug.h ├── eggaccelerators.c ├── eggaccelerators.h ├── glade-resources.gresource.xml ├── key_grabber.c ├── key_grabber.h ├── screen-size.c ├── screen-size.h ├── tilda-cli-options.c ├── tilda-cli-options.h ├── tilda-context-menu.c ├── tilda-context-menu.h ├── tilda-dbus-actions.c ├── tilda-dbus-actions.h ├── tilda-dbus-actions.xml ├── tilda-enum-types.c.template ├── tilda-enum-types.h.template ├── tilda-keybinding.c ├── tilda-keybinding.h ├── tilda-lock-files.c ├── tilda-lock-files.h ├── tilda-match-registry.c ├── tilda-match-registry.h ├── tilda-palettes.c ├── tilda-palettes.h ├── tilda-regex.h ├── tilda-search-box.c ├── tilda-search-box.h ├── tilda-search-box.ui ├── tilda-url-spawner.c ├── tilda-url-spawner.h ├── tilda.c ├── tilda.h ├── tilda.ui ├── tilda_terminal.c ├── tilda_terminal.h ├── tilda_window.c ├── tilda_window.h ├── tomboykeybinder.c ├── tomboykeybinder.h ├── wizard.c └── wizard.h ├── tilda-dbus.desktop.in ├── tilda.appdata.xml ├── tilda.desktop.in └── tilda.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | m4 3 | po/*~ 4 | po/*.gmo 5 | po/*.sed 6 | po/*.sin 7 | Makefile 8 | Makefile.in 9 | aclocal.m4 10 | autom4te.cache/ 11 | compile 12 | config.guess 13 | config.log 14 | config.rpath 15 | config.status 16 | config.sub 17 | configure 18 | depcomp 19 | install-sh 20 | missing 21 | po/Makefile 22 | po/Makefile.in 23 | po/Makefile.in.in 24 | po/Makevars.template 25 | po/POTFILES 26 | po/Rules-quot 27 | po/en@boldquot.header 28 | po/en@quot.header 29 | po/stamp-po 30 | po/tilda.pot 31 | src/.deps/ 32 | src/Makefile 33 | src/Makefile.in 34 | src/key_converter.c 35 | src/glade-resources.c 36 | src/glade-resources.h 37 | src/tilda 38 | stamp-h1 39 | src/tilda.ui~ 40 | config.h 41 | config.h.in 42 | config.h.in~ 43 | tilda.desktop 44 | ylwrap 45 | ABOUT-NLS 46 | INSTALL 47 | *.anjuta* 48 | .project 49 | .cproject 50 | .kdev4 51 | .idea 52 | build/ 53 | cmake-build-debug/ 54 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # Current developers 2 | Sebastian Geiger lanoxx@gmx.net 3 | 4 | # Previous developers 5 | Tristan Sloughter sloutri@iit.edu 6 | Ira Snyder tilda@irasnyder.com 7 | Ken Dreyer kdreyer@chicagolug.org 8 | Jordan Wilberding diginux@gmail.com 9 | Daniel Krol dan@danielkrol.com (configurable keyboard shortcuts feature) 10 | 11 | Thanks to the everyone who has contributed some patches and helped testing tilda. 12 | -------------------------------------------------------------------------------- /HACKING.md: -------------------------------------------------------------------------------- 1 | # Compiling and Installing 2 | 3 | ## Dependencies 4 | 5 | * Glib >= 2.30 - http://developer.gnome.org/glib/2.30/ 6 | * Gtk+3 >= 3.22 - http://developer.gnome.org/gtk3/3.22/ 7 | * VTE >= 2.91 - http://developer.gnome.org/vte/0.30/ 8 | * libConfuse - http://www.nongnu.org/confuse/ 9 | * libx11-dev - http://www.x.org/wiki/ 10 | 11 | On Ubuntu based system install dependencies with: 12 | 13 | sudo apt-get install git dh-autoreconf autotools-dev debhelper \ 14 | libconfuse-dev libgtk-3-dev libpcre2-dev libvte-2.91-dev pkg-config 15 | 16 | You possibly need other packages such as `gettext`, `automake`, 17 | `autoconf`, `autopoint`, and X11 development libraries. 18 | 19 | On Fedora: 20 | 21 | # This may be outdated (see Ubuntu example above, for a more thorough list) 22 | sudo yum install git automake libconfuse-devel vte3-devel gtk3-devel \ 23 | glib-devel gettext-devel 24 | 25 | The dependencies section above is complete but the sample command may not be 26 | complete, depending on your system you may need to install additional packages. 27 | Please carefully read the output of the `autogen.sh` (see below) for more 28 | information of what you need to install. 29 | 30 | ## Compiling 31 | 32 | Generally if you have installed the development packages (e.g. `*-dev` or 33 | `*-devel`) of the dependencies above and the autotools suite then it should 34 | be possible to compile with: 35 | 36 | mkdir build 37 | cd build 38 | ../autogen.sh --prefix=/usr 39 | make --silent 40 | 41 | Changing to `build/` and calling `autogen.sh` relative from there makes sure 42 | that we perform an out-of-tree build and all generated files are stored inside 43 | `build/`. This way build artifacts will not clutter the source directory. 44 | For debugging, we can use the `--enable-maintainer-flags` option, which enables 45 | additional debug flags and runtime debug messages as well as more compile-time 46 | warnings: 47 | 48 | ../autogen.sh --enable-maintainer-flags 49 | 50 | Alternatively, you can enable these separately by adding 51 | `--debug-functions` or `--enable-debug` to the autogen call: 52 | 53 | ../autogen.sh --enable-debug-functions --enable-debug 54 | 55 | If you get the following error message, then you are missing the `autopoint` 56 | binary which is part of the autotools suite. On Ubuntu the `dh-autoreconf` 57 | package installs it along with automake, autoconf and autoreconf. 58 | 59 | Can't exec "autopoint": No such file or directory at [\] 60 | /usr/share/autoconf/Autom4te/FileUtils.pm line 345. 61 | 62 | You do not need the `--silent` option, but I prefer to use it to reduce the 63 | output a bit. If you experience any problem during build, then drop the 64 | `--silent` option. 65 | 66 | ## Installing 67 | 68 | After you have compiled the package run the following command to install tilda 69 | to the prefix that you have chosen before: 70 | 71 | sudo make install 72 | 73 | If you don't want to install to the `/usr` prefix, choose some other prefix 74 | when you run the `autogen.sh` script, such as `/opt/tilda` and add it to your 75 | path. 76 | 77 | # Packaging for Debian 78 | 79 | This section explains how to package Tilda for Debian and Debian derived 80 | distributions. 81 | 82 | ## Preparation before building the package 83 | 84 | In order to build a package which can be uploaded to some Debian based 85 | distribution the following steps are necessary. Replace '#' with the number of 86 | the current minor and patch release version. 87 | 88 | 1. Check out the latest stable branch (e.g. tilda-1-#) 89 | and add any changes or bugfixes which you want to include, 90 | then commit these changes. Tilda stable branches are named 91 | `tilda--` and all patch level releases for the same minor 92 | release go into that branch. 93 | 2. Change into the `po/` folder, run `make update-po` and commit any changed 94 | `.po` files in the `po` folder. If this change is forgotten, then after 95 | running `make distcheck` below there may be uncommitted changed to the `po` 96 | folder in the source tree. 97 | 3. Update the `Changelog` and commit it: 98 | 99 | git commit -m "Update the change log for 1.#.#" 100 | 4. Update the version number in `configure.ac` and make 101 | a commit, the version number as commit message: 102 | 103 | git commit -m "1.#.#" 104 | 5. Create a tarball from the build folder: 105 | 106 | cd build/ 107 | make distcheck 108 | 109 | This will give you a tarball in the build folder named `tilda-1.#.#`, the 110 | tarball needs to be copied to the location where you are building the 111 | package and it needs to be renamed (or symlinked) as 112 | `tilda_1.#.#.orig.tar.gz`. 113 | 114 | 6. Checkout the [packaging files for tilda][1] and update the change log at 115 | `debian/changelog` such that it contains an entry for the latest version 116 | of tilda. Note, the `debian/changelog` should not contain information about 117 | tilda specific changes but about changes related to the Debian packaging. 118 | 119 | ## Building a package 120 | 121 | With the above `make distcheck` command you get a tarball from which a Debian 122 | package can be build. A Debian package consists of a separate source and binary 123 | package. The following steps document the basic commands that are required to 124 | build both the source package and the binary package, to verify that both are 125 | correct and to upload the source package to *mentors.debian.org*. 126 | 127 | I am using **pbuilder** to build the source and binary packages. 128 | Please refer to the man pages **pbuilder(8)** on howto 129 | setup the base image. I also use **pdebuild** as a convenient script to 130 | run `debuild` inside the **pbuilder** environment (see **pdebuild(1)**). 131 | 132 | The following process creates several files and packages in the folder from 133 | where these commands are executed, its useful to perform these commands in a 134 | separate folder such as `tilda-releases`: 135 | 136 | 1. `mkdir tilda-releases; cd tilda-releases`. 137 | 2. Copy the release tarball to the current location and extract it: 138 | `tar -xf tilda_1.2.#.orig.tar.gz` 139 | 3. `cd tilda-1.#.#` 140 | 4. Checkout the `tilda-debian` [repository][1] from Github and copy the 141 | `debian/` folder to `tilda-1.#.#/`. 142 | 5. To build the source package you need to run **debuild**. You can use one of 143 | the following two methods to do this: 144 | * Run **debuild** inside a change root by using `pdebuild`: 145 | 146 | sudo pdebuild --use-pdebuild-internal \ 147 | -- --basetgz ~/pbuilder/unstable-base.tgz 148 | * Run `debuild` directly from the current folder (e.g. from `tilda-1.#.#/`) 149 | 6. If `debuild` finishes without a problem next run `pbuilder`, this will 150 | verify that the package is buildable (without warnings or errors) in a clean 151 | environment: 152 | 153 | sudo pbuilder --build --basetgz ~/pbuilder/unstable-base.tgz \ 154 | tilda_1.#.#-1.dsc 155 | 7. Optionally run `lintian`: 156 | 157 | lintian -I --show-overrides tilda_1.#.#-1_amd64.changes 158 | 8. Run `debsign` to sign the package with your PGP key: 159 | 160 | debsign tilda_1.#.#-1_amd64.changes 161 | 9. If `pbuilder` does not complain and you don not see any warnings in 162 | `lintian`, then upload the package to mentors: 163 | 164 | dput mentors tilda_1.#.#-1_amd64.changes 165 | 166 | ## Notes on pbuilder 167 | 168 | The commands above assume an up to date pbuilder image for debian unstable 169 | which can be created via: 170 | 171 | mkdir ~/pbuilder; cd ~/pbuilder 172 | sudo pbuilder create --basetgz unstable-base-test.tgz --distribution sid \ 173 | --mirror http://deb.debian.org/debian 174 | 175 | The `--mirror` option is necessary when creating the image on downstream 176 | distributions such as Ubuntu. In such a case pbuilder would use the Ubuntu 177 | mirror and will complain that the repository has no `unstable` release. 178 | 179 | [1]: https://salsa.debian.org/debian/tilda/ 180 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ## Process this file with automake to produce a Makefile.in 2 | # vim: set noexpandtab ts=8 sts=8 sw=8: 3 | 4 | SUBDIRS = po 5 | 6 | CLEANFILES = tilda.desktop tilda-dbus.desktop 7 | 8 | MAINTAINERCLEANFILES = \ 9 | ABOUT-NLS \ 10 | Makefile.in \ 11 | aclocal.m4 \ 12 | stamp-h1 \ 13 | missing \ 14 | install-sh \ 15 | decomp \ 16 | compile \ 17 | INSTALL \ 18 | m4/*.m4 \ 19 | config.h \ 20 | config.guess \ 21 | config.rpath \ 22 | config.sub \ 23 | configure \ 24 | depcomp \ 25 | m4/Makefile.in \ 26 | po/Makefile.in.in \ 27 | po/Makevars.template \ 28 | po/Rules-quot \ 29 | po/boldquot.sed \ 30 | po/en@boldquot.header \ 31 | po/en@quot.header \ 32 | po/insert-header.sin \ 33 | po/quot.sed \ 34 | po/remove-potcdate.sin \ 35 | po/tilda.pot \ 36 | config.h.in \ 37 | config.h.in~ 38 | 39 | Applicationsdir = ${datadir}/applications 40 | Applications_DATA = tilda.desktop tilda-dbus.desktop 41 | 42 | Appdatadir = ${datadir}/metainfo 43 | Appdata_DATA = tilda.appdata.xml 44 | 45 | Pixmapsdir = ${datadir}/pixmaps 46 | Pixmaps_DATA = tilda.png 47 | 48 | EXTRA_DIST = tilda.desktop.in tilda-dbus.desktop.in tilda.png tilda.appdata.xml README.md COPYING.GPLv3 49 | 50 | %.desktop: %.desktop.in 51 | sed -e 's|\@BINDIR\@|$(bindir)|' \ 52 | -e 's|\@PIXMAPSDIR\@|$(Pixmapsdir)|' $< > $@ 53 | 54 | ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} 55 | 56 | 57 | bin_PROGRAMS = 58 | 59 | man1_MANS = 60 | 61 | include data/Makefile.am 62 | include src/Makefile.am 63 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanoxx/tilda/51bfe3c7cb755499fa22d00134d68b86a9fdaafd/NEWS -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # What is Tilda? 2 | 3 | Tilda is a terminal emulator and can be compared with other popular terminal emulators such as 4 | gnome-terminal (Gnome), Konsole (KDE), xterm and many others. The specialities of Tilda 5 | are that it does not behave like a normal window but instead it can be pulled up and down from the top 6 | of the screen with a special hotkey. Additionally Tilda is highly configurable. It is possible to configure the 7 | hotkeys for keybindings, change the appearance and many options that affect the behavior of Tilda. The screen shots 8 | below show some of the options that Tilda provides. 9 | 10 | ## Tilda Terminal 11 | ![Tilda window with search bar](images/tilda_terminal_with_search_bar.png) 12 | 13 | Starting with version 1.3 Tilda comes with a search bar. Currently we support searching forwards and backwards 14 | as well as options to search case sensitive and to use regular expressions. The search bar can be activated from 15 | the context menu or with a configurable hotkey that defaults to `F` 16 | ## General options 17 | ![General](images/tilda_general-16-9.png) 18 | 19 | ## Title and Command 20 | ![Title And Command](images/tilda_title_and_command-16-9.png) 21 | 22 | ## Appearance options 23 | ![Appearance](images/tilda_appearance-16-9.png) 24 | 25 | ## Colors 26 | ![Colors](images/tilda_colors-16-9.png) 27 | 28 | ## Keybindings options 29 | 30 | Starting with version 1.4 Tilda's keybindings page switches to 31 | a new list based layout that is easier to use. 32 | 33 | ![Keybindings](images/tilda_keybindings-16-9.png) 34 | 35 | ## Supported Platforms 36 | Tilda works only on Xorg-based desktops. Previously that 37 | meant that virtually all Linux distributions and some BSD's would be supported. 38 | Recently however, some Linux distributions 39 | (such as Ubuntu 17.10 and later) have started to use Wayland as their 40 | default display server. Tilda can run on Wayland via the Xwayland plugin and 41 | the most recent version of Tilda has implemented a D-Bus interface, that 42 | allows to toggle the Tilda window via a D-Bus action. To enable this, users 43 | need to start Tilda with the `--dbus` argument, and configure a (global) 44 | shortcut key within desktop-environment, passing `-T 0` argument to toggle 45 | the first instance. If additional tilda processes are running, then each 46 | process increments this value by one (i.e., `-T 1` for the second instance). 47 | 48 | # Installing Tilda 49 | 50 | Tilda should be packaged for your distribution if you are running Debian or any Debian derived distribution such as 51 | Ubuntu or Linux Mint. For other distributions please check your package manager if it provides Tilda. You can also 52 | install Tilda from source. For instructions to compile, install and optionally package tilda please see 53 | **[HACKING.md](HACKING.md)**. 54 | 55 | # Running Tilda 56 | 57 | Once you have installed tilda, it should have automatically registered a menu entry in your desktops application menu. 58 | Alternatively, you can run `tilda` from your command line. 59 | 60 | The first time you run Tilda, it will create the default configuration file for 61 | you, and show the configuration wizard. If you do not want to change any 62 | settings, just press the "OK" button to accept the defaults. 63 | 64 | The default keybindings to show and hide Tilda are as follows: 65 | 66 | * F1 - the first instance 67 | * F2 - the second instance 68 | * F3 - the third instance 69 | * ... 70 | 71 | Other default keybindings are: 72 | 73 | * Shift-Ctrl-T - Open new tab 74 | * Ctrl-PageUp - Next tab 75 | * Ctrl-PageDown - Previous tab 76 | * Shift-Ctrl-W - Close current tab 77 | * Shift-Ctrl-Q - Exit Tilda 78 | 79 | # Specifying your own keybinding to hide / show Tilda 80 | 81 | We, the developers, have attempted to make the keybinding setting work with as 82 | little trouble as possible. Some example keybindings follow: 83 | 84 | | Keybinding String | Notes | 85 | |-------------------|-------------------------------------------------------------------| 86 | | `grave` | This will use the tilde key. Many people want this. | 87 | | `~` | This is the same as `grave` | 88 | | `space` | This will use the spacebar to show / hide Tilda. NOT RECOMMENDED! | 89 | | `A` | Press Shift, Control, and the "a" key at the same time | 90 | | `space` | Press Shift and the spacebar at the same time | 91 | | `z` | Press Control and the "z" key at the same time | 92 | 93 | That should cover most of the cases. If you want to use something else, it 94 | probably follows the pattern, so give it a try. Alternatively, you can use the 95 | configuration wizard, and press the "Pull Down Terminal" button on the 96 | "Keybindings" tab, then type the combination you want to use. Hopefully, Tilda 97 | will be able to grab it for you. The `` key cannot be grabbed, so at the moment 98 | combinations such as `` are not possible. 99 | 100 | # Files that Tilda creates 101 | 102 | Since approximately version 0.9.6 Tilda adheres to the XDG Base Directory Specification and 103 | creates its files in the $XDG_CONFIG_HOME and $XDG_CACHE_HOME folders which normally default to 104 | ~/.config/ and ~/.cache/. Tilda will create a lock file in the cache directory 105 | each time it starts, to keep track of how many instances are running: 106 | 107 | ~/.cache/tilda/locks/lock_$PID_$INSTANCE 108 | 109 | Tilda will also create the config files in: 110 | 111 | ~/.config/tilda/config_$INSTANCE 112 | 113 | where `$INSTANCE` is the number of how many instances are running and 114 | `$PID` the process id. Tilda automatically migrates the files for you if it detects configuration file 115 | at the old location `~/.tilda`. 116 | 117 | # Getting more help / Questions and Comments 118 | 119 | To get more help, you should first open a command prompt, and run `tilda 120 | --help`. You can also take a look at the **[Wiki](https://github.com/lanoxx/tilda/wiki)**, or email 121 | questions and comments to anyone listed in the [AUTHORS](AUTHORS) file. 122 | 123 | # Reporting Bugs 124 | 125 | We have done our best to make sure that Tilda is free from bugs, but it is 126 | inevitable that we have missed some. 127 | 128 | You may open bugs in the **[issue section](http://github.com/lanoxx/tilda/issues)** or email them to the 129 | developers directly. 130 | 131 | # Contributing to Tilda 132 | 133 | Tilda is an open source project that lives by the help of volunteers 134 | who fix bugs and implement new features in their spare time. Everybody is 135 | welcome to join and help us to fix bugs or to implement new features. 136 | Pull requests and patches are always welcome. 137 | 138 | ## Prerequisites 139 | 140 | Tilda is written in C with the use of the libraries 141 | **glib**, **GTK+**, **libconfuse** and **X11**. You should have a 142 | good background in C and some experience with GTK and glib already. Some 143 | areas of tilda will also require to know a little about X11 programming. 144 | 145 | ## What to work on? 146 | 147 | If you already have the necessary background feel free to submit a patch 148 | that fixes an issue or implements a new feature. If you are unsure if 149 | your patch will be accepted then open an issue first, describe your issue 150 | and ask if its likely that the patch gets accepted. 151 | 152 | You can also look into the [TODO.md](TODO.md) file and see if there 153 | is something there that you would like to do. 154 | 155 | ## Getting help 156 | 157 | Feel free to mail the developers if you have questions about the 158 | tilda source code or if you are unsure how something works. 159 | 160 | # License 161 | 162 | The majority of tilda source code is licensed under GPLv2 or later, but 163 | individual source files may be licensed under GPLv3 or later. 164 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # Feature Requests / Improvements 2 | 3 | * Dragable bar at the bottom to change Tilda's height 4 | * Ability to disable keyboard accelerators (close tab, new tab, etc) 5 | * Session support, so Tilda will load with the same number of tabs that it had 6 | upon closing. 7 | * Ability to rename a tab manually 8 | 9 | # Future Plans 10 | 11 | * DBus-ize Tilda 12 | This will make Tilda more of a long-running daemon than a terminal. What I 13 | envision is one Tilda process per user, with one config file, managing all of 14 | the Tilda windows (individual terminals) that the user wants. Also, expose all 15 | of the terminal's properties over DBus, so a completely seperate config 16 | program can be written. Also, things like "open a new tab in terminal 3, and 17 | launch XYZ in it" should be possible, and easy. 18 | 19 | Unfortunately, to support this, I am thinking about moving away from 20 | libConfuse, and moving to the built-in GLib key-value parser (INI-like). This 21 | should allow a config file like: 22 | 23 | [global] 24 | setting1 = value1 25 | setting2 = value2 26 | 27 | [terminal1] 28 | setting1 = value3 29 | 30 | Which means (to me) that all terminals should have the settings from the 31 | global section, but terminal1 will have setting1 overridden to a different 32 | value. This could be used to give different backgrounds or different fonts 33 | in each terminal, for example, but keep all other properties the same. 34 | 35 | Of course, the DBus stuff should probably be optional, so that you don't have 36 | to have it installed, nor running. You should be able to start a Tilda which 37 | is configured with DBus, but not have DBus running. It would be nice if Tilda 38 | didn't die when DBus dies out from under us. 39 | 40 | # Possible Translation Problems 41 | 42 | Change "Animation Delay" to "Animation Duration" 43 | "Notebook" should be changed to "Window", probably 44 | "tab_pos" error msg (in a switch stmt) should be changed. 45 | 46 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "This script will generate the initial build system files to compile" 4 | echo "tilda successfully. When done it will call the ./configure script" 5 | echo "and pass on any options which you passed to this script" 6 | echo "See ./configure --help to know which options are available" 7 | echo 8 | echo "When it is finished, take the usual steps to install:" 9 | echo "make" 10 | echo "make install" 11 | echo 12 | 13 | (automake --version) < /dev/null > /dev/null 2>&1 || { 14 | echo; 15 | echo "You must have automake installed to compile tilda"; 16 | echo; 17 | exit 1; 18 | } 19 | 20 | (autoconf --version) < /dev/null > /dev/null 2>&1 || { 21 | echo; 22 | echo "You must have autoconf installed to compile tilda"; 23 | echo; 24 | exit 1; 25 | } 26 | 27 | (autopoint --version) < /dev/null > /dev/null 2>&1 || { 28 | echo; 29 | echo "You must have autopoint installed to compile tilda"; 30 | echo; 31 | exit 1; 32 | } 33 | 34 | test -n "$srcdir" || srcdir=$(dirname "$0") 35 | test -n "$srcdir" || srcdir=. 36 | 37 | olddir=$(pwd) 38 | 39 | cd $srcdir 40 | 41 | (test -f configure.ac) || { 42 | echo "*** ERROR: Directory '$srcdir' does not look like the top-level project directory ***" 43 | exit 1 44 | } 45 | 46 | # shellcheck disable=SC2016 47 | PKG_NAME=$(autoconf --trace 'AC_INIT:$1' configure.ac) 48 | 49 | if [ "$#" = 0 -a "x$NOCONFIGURE" = "x" ]; then 50 | echo "*** INFO: 'configure' will be run with no arguments." >&2 51 | echo "*** If you wish to pass any to it, please specify them on the" >&2 52 | echo "*** '$0' command line." >&2 53 | echo "" >&2 54 | fi 55 | 56 | echo "Generating build system configuration for tilda, please wait..." 57 | echo; 58 | 59 | # Autoreconf will call run autopoint, aclocal, autoconf, autoheader and automake 60 | # to setup and configure the build environment 61 | autoreconf --verbose --install --symlink --force || { 62 | echo; 63 | echo "autoreconf has encountered an error."; 64 | echo; 65 | exit 1; 66 | } 67 | 68 | # Next we invoke the configure script. "$@" contains the arguments that 69 | # were passed to this script and we used it to forward them to configure. 70 | 71 | cd "$olddir" 72 | if [ "$NOCONFIGURE" = "" ]; then 73 | echo "Running configure..." 74 | $srcdir/configure "$@" || exit 1 75 | 76 | if [ "$1" = "--help" ]; then exit 0 else 77 | echo "Now type 'make' to compile $PKG_NAME" || exit 1 78 | fi 79 | else 80 | echo "Skipping configure process." 81 | fi 82 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | dnl **************************************************************************** 2 | dnl Tilda autoconf configuration file. 3 | dnl Use autogen.sh to bootstrap the build system. 4 | dnl **************************************************************************** 5 | 6 | m4_define ([tilda_issues], 7 | [https://github.com/lanoxx/tilda/issues]) 8 | 9 | m4_define ([tilda_repository], 10 | [https://github.com/lanoxx/tilda]) 11 | 12 | AC_PREREQ([2.71]) 13 | 14 | AC_INIT([Tilda], 15 | [1.6-alpha], 16 | [tilda_issues], 17 | [tilda], 18 | [tilda_repository]) 19 | 20 | AC_CONFIG_AUX_DIR([build-aux]) 21 | AC_CONFIG_SRCDIR([src/tilda.c]) 22 | AC_CONFIG_HEADERS([config.h]) 23 | 24 | AM_INIT_AUTOMAKE([foreign subdir-objects]) 25 | 26 | # We are going to use silent builds which have a much 27 | # nicer output. More information can be found here: 28 | # https://wiki.gnome.org/Initiatives/GnomeGoals/NicerBuilds 29 | AM_SILENT_RULES([yes]) 30 | 31 | # See http://www.gnu.org/savannah-checkouts/gnu/automake/manual/html_node/maintainer_002dmode.html 32 | # for an explanation of using this macro. The short explanation is: 33 | # AM_MAINTAINER_MODE is bad but 34 | # AM_MAINTAINER_MODE([enable]) is good 35 | AM_MAINTAINER_MODE([enable]) 36 | 37 | # This registers the option '--enable-maintainer-flags' to the ./configure script 38 | # If this option is set then it activates both the '--enable-debug' and '--enable-debug-functions' 39 | # options that are defined below. It also activates several flags to the compile such that it 40 | # will show more warnings and errors to indicate problems in the source code. 41 | AC_ARG_ENABLE([maintainer-flags], 42 | [AS_HELP_STRING([--enable-maintainer-flags],[\ 43 | Enables extra debugging; use this option if you want to develop for tilda, 44 | but to not use it as an end user if you just want to compile and use tilda. \ 45 | This option includes the --enable-debug and --enable-debug-functions \ 46 | options. And sets several CFLAGS to enable more gcc warnings and errors.])]) 47 | 48 | if test "x$enable_maintainer_flags" = "xyes"; then 49 | enable_debug="yes" 50 | enable_debug_functions="yes" 51 | CFLAGS="$CFLAGS \ 52 | -Wall \ 53 | -Wextra \ 54 | -fno-common \ 55 | -Wstrict-aliasing=2 \ 56 | -Wshadow \ 57 | -Wmissing-prototypes \ 58 | -Wmissing-declarations \ 59 | -Wcast-align \ 60 | -Wuninitialized \ 61 | -Wno-strict-aliasing \ 62 | -Werror=pointer-arith \ 63 | -Werror=missing-declarations \ 64 | -Werror=redundant-decls \ 65 | -Werror=empty-body \ 66 | -Werror=format \ 67 | -Werror=format-security \ 68 | -Werror=format-nonliteral \ 69 | -Werror=init-self \ 70 | -Werror=vla \ 71 | -Wno-unused-parameter \ 72 | " 73 | fi 74 | 75 | # This registers the option '--enable-debug' in the ./configure script 76 | # If this option is set, then the the options -g and -ggdb will be 77 | # passed to the compiler. 78 | AC_ARG_ENABLE([debug], 79 | [AS_HELP_STRING([--enable-debug],[Enables extra debugging output and \ 80 | sets debug flags for gdb])]) 81 | 82 | if test "x$enable_debug" = "xyes"; then 83 | AC_DEFINE([DEBUG], [1], [Enable extra debugging output]) 84 | CFLAGS="$CFLAGS -g -ggdb" 85 | fi 86 | 87 | # This registers the option '--debug-functions' in the ./configure script 88 | # If this option is set, then the name of each entered function will be 89 | # printed on the shell. 90 | AC_ARG_ENABLE([debug-functions], 91 | [AS_HELP_STRING([--enable-debug-functions],[Enables function call tracing. \ 92 | When this option is enabled tilda will print \ 93 | the name of each function that is called to the \ 94 | console.])]) 95 | 96 | if test "x$enable_debug_functions" = "xyes"; then 97 | AC_DEFINE([DEBUG_FUNCTIONS], [1], [Enable function call tracing]) 98 | fi 99 | 100 | AC_ARG_ENABLE([clang], 101 | [AS_HELP_STRING([--enable-clang],[use clang instead of gcc as C compiler.])]) 102 | 103 | #Use C99 compilation mode 104 | if test "x$enable_clang" = "xyes"; then 105 | # clang uses c99 mode by default, so we just set CC to clang and we are done 106 | CC="clang"; 107 | else 108 | # We do not need to set CC as the default is gcc, but we need to set it to 109 | # use C99 compilation mode 110 | CFLAGS="$CFLAGS -std=c99"; 111 | fi 112 | 113 | AC_ARG_ENABLE([lto], 114 | [AS_HELP_STRING([--enable-lto],[Optimize at link time. This enables the compiler \ 115 | to do a better job at optimization and (hopefully) \ 116 | produce smaller binaries.])]) 117 | 118 | if test "x$enable_lto" = "xyes"; then 119 | CFLAGS="$CFLAGS -flto" 120 | if test "$CC" != "clang"; then 121 | # If the user has enabled lto explicitly, we assume he has made sure 122 | # that his toolchain can indeed handle lto objects. 123 | CFLAGS="$CFLAGS -fno-fat-lto-objects" 124 | fi 125 | # In the case of lto optimizations, we need to pass the optimization options 126 | # to the linker as well as telling it to use the linker plugin. 127 | LDFLAGS="$LDFLAGS $CFLAGS -fuse-linker-plugin" 128 | fi 129 | 130 | 131 | 132 | AC_PATH_PROG(GLIB_MKENUMS, glib-mkenums, no) 133 | if test x$GLIB_MKENUMS = xno; then 134 | AC_MSG_ERROR(Could not find a glib-mkenums in your PATH) 135 | fi 136 | 137 | AC_PATH_PROG(GLIB_COMPILE_RESOURCES, glib-compile-resources, no) 138 | if test x$GLIB_COMPILE_RESOURCES = xno; then 139 | AC_MSG_ERROR(Could not find a glib-compile-resources in your PATH) 140 | fi 141 | 142 | AC_PATH_PROG(GDBUS_CODEGEN, gdbus-codegen, no) 143 | if test x$GDBUS_CODEGEN = xno; then 144 | AC_MSG_ERROR(Could not find a glib-codegen binary in your PATH) 145 | fi 146 | 147 | # Checks for programs. 148 | AC_PROG_CC 149 | AM_PROG_CC_C_O 150 | 151 | # This will initialize the internationalization 152 | # capabilities of glib (glib/gi18n.h) and gettext 153 | AM_GNU_GETTEXT_VERSION([0.18.1]) 154 | AM_GNU_GETTEXT([external]) 155 | # Checks for libraries. 156 | PKG_PROG_PKG_CONFIG 157 | PKG_CHECK_MODULES([GTK], [gtk+-3.0 >= 3.10.0]) 158 | PKG_CHECK_MODULES([VTE], [vte-2.91 >= 0.40]) 159 | PKG_CHECK_MODULES([LIBCONFUSE], [libconfuse]) 160 | PKG_CHECK_MODULES([X11], [x11]) 161 | 162 | # Checks for header files. 163 | AC_CHECK_HEADERS([fcntl.h malloc.h stdlib.h string.h strings.h sys/ioctl.h unistd.h]) 164 | 165 | # Checks for typedefs, structures, and compiler characteristics. 166 | AC_C_CONST 167 | AC_TYPE_PID_T 168 | AC_TYPE_SIZE_T 169 | 170 | # Checks for library functions. 171 | AC_FUNC_MALLOC 172 | AC_FUNC_STRTOD 173 | AC_CHECK_FUNCS([mkdir strcasecmp strchr strncasecmp strstr strtol]) 174 | 175 | AC_CONFIG_FILES([Makefile 176 | po/Makefile.in]) 177 | AC_OUTPUT 178 | 179 | dnl --------------------------------------------------------------------------- 180 | dnl - Show summary 181 | dnl --------------------------------------------------------------------------- 182 | 183 | dnl The following 'for' block splits the CFLAGS variable into multiple lines of 4 options per line 184 | cflaglines="" 185 | cflagcount=0 186 | for flag in ${CFLAGS}; do 187 | cflaglines=$cflaglines$flag" " 188 | cflagcount=$(($cflagcount+1)) 189 | if (( $cflagcount % 4 == 0)); then 190 | dnl Here we concatenate the current cflaglines variable with a newline and enough spaces 191 | dnl such that the lines are correctly indented. Do not try to indent or reformat the 192 | dnl position of the double quotes (\"). 193 | cflaglines=$cflaglines" 194 | " 195 | fi 196 | done; 197 | 198 | echo " 199 | ${PACKAGE} $VERSION 200 | `echo ${PACKAGE} $VERSION | sed "s/./=/g"` 201 | 202 | prefix: ${prefix} 203 | datarootdir: ${datarootdir} 204 | datadir: ${datadir} 205 | pkgdatadir: `if test x${pkgdatadir} != "x"; then echo ${pkgdatadir}; else echo ${datadir}/${PACKAGE}; fi` 206 | source code location: ${srcdir} 207 | compiler: ${CC} 208 | cflags: ${cflaglines} 209 | Maintainer mode: ${USE_MAINTAINER_MODE} 210 | VTE: ${vte_package} 211 | Use *_DISABLE_DEPRECATED: ${enable_deprecation_flags} 212 | " 213 | -------------------------------------------------------------------------------- /data/Makefile.am: -------------------------------------------------------------------------------- 1 | include $(srcdir)/data/man/Makefile.am 2 | -------------------------------------------------------------------------------- /data/Readme.md: -------------------------------------------------------------------------------- 1 | # Tilda Man Page 2 | 3 | The tilda man page is generated by the build system from the `tilda.1.in` 4 | template. During the generation of the man page the version placeholder 5 | is replaced by the current tilda version. 6 | 7 | # Development 8 | 9 | To make changes to the man page use the following steps: 10 | 11 | 1. Modify the template (e.g. `tilda.1.in`). 12 | 2. Build the project via `make` from the `build` dir. 13 | 3. Open the build man page via `man ./data/man/tilda.1`. This must be executed 14 | relative to the build directory. 15 | -------------------------------------------------------------------------------- /data/man/Makefile.am: -------------------------------------------------------------------------------- 1 | data/man/tilda.1: $(srcdir)/data/man/tilda.1.in $(srcdir)/configure.ac $(srcdir)/data/man/Makefile.am 2 | $(AM_V_GEN) mkdir -p data/man && sed -e 's|\@VERSION\@|$(VERSION)|' $< > $@ 3 | 4 | man1_MANS += \ 5 | data/man/tilda.1 \ 6 | $(NULL) 7 | 8 | EXTRA_DIST += data/man/tilda.1.in 9 | 10 | CLEANFILES += data/man/tilda.1 11 | -------------------------------------------------------------------------------- /data/man/tilda.1.in: -------------------------------------------------------------------------------- 1 | .\" Copyright (c) 2023, Sebastian Geiger (lanoxx@gmx.net) 2 | .\" 3 | .\" Copyright (c) 2012, Davide Truffa 4 | .\" 5 | .\" %%%LICENSE_START(VERBATIM) 6 | .\" Permission is granted to make and distribute verbatim copies of this 7 | .\" manual provided the copyright notice and this permission notice are 8 | .\" preserved on all copies. 9 | .\" 10 | .\" Permission is granted to copy and distribute modified versions of 11 | .\" this manual under the conditions for verbatim copying, provided that 12 | .\" the entire resulting derived work is distributed under the terms of 13 | .\" a permission notice identical to this one. 14 | .\" 15 | .\" Since the Linux kernel and libraries are constantly changing, this 16 | .\" manual page may be incorrect or out-of-date. The author(s) assume. 17 | .\" no responsibility for errors or omissions, or for damages resulting. 18 | .\" from the use of the information contained herein. The author(s) may. 19 | .\" not have taken the same level of care in the production of this. 20 | .\" manual, which is licensed free of charge, as they might when working. 21 | .\" professionally. 22 | .\" 23 | .\" Formatted or processed versions of this manual, if unaccompanied by 24 | .\" the source, must acknowledge the copyright and authors of this work. 25 | .\" %%%LICENSE_END 26 | .TH "TILDA" "1" "Jan 2024" "tilda @VERSION@" "User Commands" 27 | .SH "NAME" 28 | tilda \- a highly configurable terminal emulator 29 | .SH "SYNOPSIS" 30 | tilda [\fB\-b|\-\-background\-color\fR \fIcolor\fR] [\fB\-c|\-\-command\fR \fIcommand\fR] [\fB\-h|\-\-hidden\fR] [\fB\-f|\-\-font\fR \fIfont\fR] [\fB\-g|\-\-config-file\fR \fIfile\fR] [\fB\-l|\-\-lines\fR \fIfile\fR] [\fB\-s|\-\-scrollbar\fR] [\fB\-w|\-\-working\-dir\fR \fIdir\fR] [\fB\-x|\-\-x\-pos\fR \fIx_pos\fR] [\fB\-y|\-\-y\-pos\fR \fIy_pos\fR] [\fB\-t|\-\-background\-alpha\fR \fIalpha\fR] [\fB\-C|\-\-config\fR] [\fB\-\-display\fR \fIdisplay\fR] 31 | .PP 32 | tilda \fB\-\-dbus\fR 33 | .PP 34 | tilda \fB\-T|\-\-toggle\-window [instance_id] 35 | .PP 36 | tilda \fB\-\-version\fR 37 | .PP 38 | tilda \fB\-\-help\fR 39 | .PP 40 | tilda \fB\-\-help-all\fR 41 | .SH "DESCRIPTION" 42 | .BR Tilda 43 | is a terminal emulator which is highly configurable. The main distinguishing feature of tilda is that it 44 | uses a configurable shortcut to show and hide the tilda window. This allows users to quickly switch between tilda 45 | and other windows only through keyboard shortcuts. When tilda is hidden it will move 46 | outside of the screen until the pull/toggle shortcut is pressed again to show the tilda window. The behaviour of 47 | tilda can be configured using the preferences dialog that is available via the context menu. A subset of the options 48 | can also be configured from the command line as documented below. 49 | .PP 50 | Please note that currently command line options override the settings in the configuration file and 51 | are persisted into the configuration file. 52 | .PP 53 | On Xorg-based desktops, Tilda is using an X11 filter function to register its 54 | hotkeys. On Wayland, this method only works while other X11-based programs are 55 | active but we cannot send hotkeys to tilda while native Wayland applications 56 | have the focus. Therefore, on Wayland desktops tilda needs to be started with 57 | D-Bus support (i.e., with \fB\-\-dbus\fR) and a global shortcut key must be 58 | registered using the desktop environment settings to send a D-Bus action to 59 | show or hide the Tilda window. 60 | .PP 61 | .SH "OPTIONS" 62 | .SS "Help Options:" 63 | .TP 64 | \fB\-?\fR, \fB\-\-help\fR 65 | Show help options 66 | .TP 67 | \fB\-\-help-all\fR 68 | Show all help options, including D-Bus and GTK options. 69 | .SS "Application Options:" 70 | .TP 71 | \fB\-b\fR, \fB\-\-background\-color\fR \fIcolor\fR 72 | Set the background \fIcolor\fR. The value can be either a standard color name from X11 or a hexadecimal value (i.e., #rgb, #rrggbb, etc.). 73 | .TP 74 | \fB\-c\fR, \fB\-\-command\fR \fIcommand\fR 75 | Run a \fIcommand\fR at startup instead of the default shell. 76 | .TP 77 | \fB\-h\fR, \fB\-\-hidden\fR 78 | Start Tilda hidden. 79 | .TP 80 | \fB\-f\fR, \fB\-\-font\fR \fIfont\fR 81 | Set the font to the Pango FontDescription specified in \fIfont\fR. Defaults to "Monospace 11". 82 | .TP 83 | \fB\-l\fR, \fB\-\-lines\fR \fIlines\fR 84 | The the scrollback buffer size to a maximum of \fIlines\fR. 85 | .TP 86 | \fB\-s\fR, \fB\-\-scrollbar\fR 87 | Show a scrollbar at the side of the terminal. 88 | .TP 89 | \fB\-v\fR, \fB\-\-version\fR 90 | Print the version, then exit. 91 | .TP 92 | \fB\-w\fR, \fB\-\-working\-dir\fR \fIdir\fR 93 | Set initial working directory to \fIdir\fR. 94 | .TP 95 | \fB\-x\fR, \fB\-\-x\-pos\fR \fIx_pos\fR 96 | Set the X position of the tilda terminal window to \fIx_pos\fR. 97 | .TP 98 | \fB\-y\fR, \fB\-\-y\-pos\fR \fIy_pos\fR 99 | Set the Y position of the tilda terminal window to \fIy_pos\fR. 100 | .TP 101 | \fB\-t\fR, \fB\-\-background-alpha\fR \fIalpha\fR 102 | Set the terminal windows transparency to \fIalpha\fR (i.e., 0\-100%). Higher values 103 | increase the level of transparency. 104 | .TP 105 | \fB\-C\fR, \fB\-\-config\fR 106 | Show the configuration wizard. 107 | .TP 108 | \fB\-\-display\fR=\fIDISPLAY\fR 109 | Set the X display to use (i.e., :0, :0.0, etc.). 110 | .SS "D-Bus Options:" 111 | .TP 112 | \fB\-\-dbus\fR 113 | Enables D-Bus support (see \fID-Bus\fR). 114 | .TP 115 | \fB\-T\fR, \fB\-\-toggle\-window\fR \fI[instance_id]\fR 116 | Toggle a Tilda window with \fIinstance_id\fR and exit. If \fIinstance_id\fR is 117 | not specified it will default to instance 0. This option provides a convenient 118 | way to toggle tilda windows on Wayland environments and is equivalent to the 119 | longer \fIdbus-send\fR command documented below. It can be used to setup a 120 | Keyboard shortcut on a Wayland-based desktop environment which will then toggle 121 | the Tilda window. Note, that this option is affected by the 122 | "Non-Focus Pull Up Behaviour" setting. 123 | .SH "NOTES" 124 | .SS D-Bus 125 | If D-Bus is enabled, then Tilda offers a method on D-Bus to toggle the Tilda Window. 126 | Each Tilda process registers its own D-Bus name, so it is possible to 127 | run multiple tilda processes each with their own config file and control 128 | them separately via D-Bus. When D-Bus is enabled, then the pull down 129 | shortcut is not registered as an Xorg filter function, and a suitable 130 | global shortcut needs to be configured in the desktop environment (see 131 | \-\-toggle\-window). You may optionally clear the pull shortcut in the settings, 132 | if D-Bus support is enabled. 133 | .PP 134 | Each Tilda instance registers itself using a dynamically generated 135 | bus name and object path using its instance number. The first Tilda 136 | instance will be on the bus name: 137 | .TP 138 | com.github.lanoxx.tilda.Actions0 139 | .PP 140 | with object path: 141 | .TP 142 | /com/github/lanoxx/tilda/Actions0 143 | .PP 144 | The interface name is always: 145 | .TP 146 | com.github.lanoxx.tilda.Actions 147 | .PP 148 | To toggle the tilda window you can use the \fB\-T|\-\-toggle\-window\fR option 149 | of tilda: 150 | .TP 151 | .EX 152 | tilda -T # toggle default instance (i.e., 0) 153 | .EE 154 | .TP 155 | .EX 156 | tilda -T 0 # explicitly toggle the specified instance (i.e., 0) 157 | .EE 158 | .PP 159 | Alternatively, you can also use the \fBdbus-send\fR command. 160 | .TP 161 | .EX 162 | dbus-send --session --type=method_call \\ 163 | --dest=com.github.lanoxx.tilda.Actions0 \\ 164 | /com/github/lanoxx/tilda/Actions0 \\ 165 | com.github.lanoxx.tilda.Actions.Toggle 166 | .EE 167 | .PP 168 | For each additional tilda instance the bus name and object path will 169 | be incremented by one (e.g. Actions1, Actions2, etc.). 170 | .PP 171 | You can use one of the above commands to register a global hotkey in your Wayland 172 | session. Under Gnome, this can be done under Settings -> Keyboard 173 | -> Keyboard Shortcuts. 174 | .SS "FILES" 175 | .PP 176 | Tilda creates its configuration files under \fB~/.config/tilda/\fR. For each instance 177 | it will create a config file named \fBconfig_\fR, where \fB\fR starts at 0 and is 178 | incremented for each additional process that is started. 179 | .PP 180 | Tilda also creates a cache directory under \fB~/.cache/tilda/locks\fR, where it will create 181 | a global lock file named \fBlock_0_0\fR and additional instance specific lock files 182 | named \fBlock__\fR, where \fB\fR is the process id and \fB\fR is the 183 | instance id. 184 | .PP 185 | You may optionally create a file named \fBstyle.css\fR and place it into the 186 | tilda config directory if you want to customize the look of tilda. 187 | .SH "BUGS" 188 | Please report bugs via Github at https://github.com/lanoxx/tilda/issues 189 | .SH "SEE ALSO" 190 | For further information visit the project repository or have a look at the 191 | wiki: https://github.com/lanoxx/tilda/wiki 192 | -------------------------------------------------------------------------------- /docs/multi-monitor-setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanoxx/tilda/51bfe3c7cb755499fa22d00134d68b86a9fdaafd/docs/multi-monitor-setup.png -------------------------------------------------------------------------------- /docs/multi-monitor-setup.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanoxx/tilda/51bfe3c7cb755499fa22d00134d68b86a9fdaafd/docs/multi-monitor-setup.xcf -------------------------------------------------------------------------------- /images/tilda_appearance-16-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanoxx/tilda/51bfe3c7cb755499fa22d00134d68b86a9fdaafd/images/tilda_appearance-16-9.png -------------------------------------------------------------------------------- /images/tilda_colors-16-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanoxx/tilda/51bfe3c7cb755499fa22d00134d68b86a9fdaafd/images/tilda_colors-16-9.png -------------------------------------------------------------------------------- /images/tilda_general-16-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanoxx/tilda/51bfe3c7cb755499fa22d00134d68b86a9fdaafd/images/tilda_general-16-9.png -------------------------------------------------------------------------------- /images/tilda_keybindings-16-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanoxx/tilda/51bfe3c7cb755499fa22d00134d68b86a9fdaafd/images/tilda_keybindings-16-9.png -------------------------------------------------------------------------------- /images/tilda_terminal_with_search_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanoxx/tilda/51bfe3c7cb755499fa22d00134d68b86a9fdaafd/images/tilda_terminal_with_search_bar.png -------------------------------------------------------------------------------- /images/tilda_title_and_command-16-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanoxx/tilda/51bfe3c7cb755499fa22d00134d68b86a9fdaafd/images/tilda_title_and_command-16-9.png -------------------------------------------------------------------------------- /po/LINGUAS: -------------------------------------------------------------------------------- 1 | bg 2 | ca 3 | cs 4 | de 5 | el 6 | en_GB 7 | es 8 | fr 9 | hr 10 | hu 11 | it 12 | lt 13 | nb 14 | pl 15 | pt 16 | pt_BR 17 | ru 18 | sk 19 | sl 20 | sv 21 | tr 22 | uk 23 | zh_CN 24 | zh_TW 25 | -------------------------------------------------------------------------------- /po/Makevars: -------------------------------------------------------------------------------- 1 | # Makefile variables for PO directory in any package using GNU gettext. 2 | 3 | # Usually the message domain is the same as the package name. 4 | DOMAIN = $(PACKAGE) 5 | 6 | # These two variables depend on the location of this directory. 7 | subdir = po 8 | top_builddir = .. 9 | 10 | # These options get passed to xgettext. 11 | XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ --keyword=col 12 | 13 | # This is the copyright holder that gets inserted into the header of the 14 | # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding 15 | # package. (Note that the msgstr strings, extracted from the package's 16 | # sources, belong to the copyright holder of the package.) Translators are 17 | # expected to transfer the copyright for their translations to this person 18 | # or entity, or to disclaim their copyright. The empty string stands for 19 | # the public domain; in this case the translators are expected to disclaim 20 | # their copyright. 21 | COPYRIGHT_HOLDER = Ira W. Snyder 22 | 23 | # This is the email address or URL to which the translators shall report 24 | # bugs in the untranslated strings: 25 | # - Strings which are not entire sentences, see the maintainer guidelines 26 | # in the GNU gettext documentation, section 'Preparing Strings'. 27 | # - Strings which use unclear terms or require additional context to be 28 | # understood. 29 | # - Strings which make invalid assumptions about notation of date, time or 30 | # money. 31 | # - Pluralisation problems. 32 | # - Incorrect English spelling. 33 | # - Incorrect formatting. 34 | # It can be your email address, or a mailing list address where translators 35 | # can write to without being subscribed, or the URL of a web page through 36 | # which the translators can contact you. 37 | MSGID_BUGS_ADDRESS = sloutri@iit.edu 38 | 39 | # This is the list of locale categories, beyond LC_MESSAGES, for which the 40 | # message catalogs shall be used. It is usually empty. 41 | EXTRA_LOCALE_CATEGORIES = 42 | -------------------------------------------------------------------------------- /po/POTFILES.in: -------------------------------------------------------------------------------- 1 | # List of source files which contain translatable strings. 2 | 3 | src/tilda.ui 4 | src/configsys.c 5 | src/tilda.c 6 | src/tilda-keybinding.c 7 | src/tilda_terminal.c 8 | src/tilda_window.c 9 | src/wizard.c 10 | src/tilda-search-box.ui 11 | src/tilda-context-menu.c 12 | src/tilda-match-registry.c 13 | -------------------------------------------------------------------------------- /po/README: -------------------------------------------------------------------------------- 1 | New Translations 2 | ================================================================================ 3 | We, the Tilda developers, have stopped using Launchpad to assist with our 4 | translation effort. It was located at 5 | https://translations.launchpad.net/tilda/trunk/+pots/tilda 6 | 7 | Please directly submit Pull Requests on GitHub to update translations or 8 | initialize new translation. 9 | 10 | 11 | How to integrate a new translation into Tilda 12 | ================================================================================ 13 | 1) Copy the LANG.po file into the po/ directory. 14 | 2) Add LANG to the po/LINGUAS file. 15 | 16 | The next time you completely rebuild and install Tilda, it will automatically 17 | compile and install the language file onto your system. Afterwards, if you run 18 | Tilda with the correct LANG environmental variable, Tilda should use your 19 | translation. 20 | 21 | 22 | How to do a new translation without Launchpad 23 | ================================================================================ 24 | # If you want to auto generate a pot file template from sources, use xgettext 25 | # from project root directory 26 | xgettext --files-from=./po/POTFILES.in --output=po/LANG.pot 27 | 28 | cd po 29 | msginit -l en_US # (for USA English. Creates en.po) 30 | 31 | # ... do the translation in your editor of choice ... 32 | 33 | # add your translation to the LINGUAS file, without the .po 34 | # extension. 35 | # 36 | # That would be "en" for the above examples 37 | # 38 | # If po/Makefile does not exist, please configure this project first: 39 | # 40 | # autoreconf --install --verbose --force 41 | # ./configure 42 | 43 | Then run the following commands: 44 | 45 | make update-po 46 | make update-gmo 47 | cd .. 48 | make 49 | 50 | -------------------------------------------------------------------------------- /po/oc.po: -------------------------------------------------------------------------------- 1 | # Occitan (post 1500) translation for tilda 2 | # Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020 3 | # This file is distributed under the same license as the tilda package. 4 | # FIRST AUTHOR , 2020. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: tilda\n" 9 | "Report-Msgid-Bugs-To: FULL NAME \n" 10 | "POT-Creation-Date: 2008-01-30 19:35-0800\n" 11 | "PO-Revision-Date: 2020-12-31 20:19+0100\n" 12 | "Last-Translator: Quentin PAGÈS\n" 13 | "Language-Team: Occitan (post 1500) \n" 14 | "MIME-Version: 1.0\n" 15 | "Content-Type: text/plain; charset=UTF-8\n" 16 | "Content-Transfer-Encoding: 8bit\n" 17 | "X-Launchpad-Export-Date: 2020-12-29 17:48+0000\n" 18 | "X-Generator: Poedit 2.4.2\n" 19 | "Language: oc\n" 20 | 21 | #: tilda.glade:7 22 | msgid "Tilda Config" 23 | msgstr "Configuracion de Tilda" 24 | 25 | #: tilda.glade:42 26 | msgid "Display on all workspaces" 27 | msgstr "Visualizar sus totes los espacis de trabalh" 28 | 29 | #: tilda.glade:55 30 | msgid "Always on top" 31 | msgstr "Totjorn visible" 32 | 33 | #: tilda.glade:70 34 | msgid "Do not show in taskbar" 35 | msgstr "Afichar pas a la barra de prètzfaches" 36 | 37 | #: tilda.glade:85 src/tilda.c:303 38 | msgid "Start Tilda hidden" 39 | msgstr "Aviar Tilda en mòde amagat" 40 | 41 | #: tilda.glade:102 42 | msgid "Show Notebook Border" 43 | msgstr "Afichar la bordadura" 44 | 45 | #: tilda.glade:117 46 | #, fuzzy 47 | msgid "Enable Double Buffering" 48 | msgstr "Inibir per aver un doble tampon per logicial." 49 | 50 | #: tilda.glade:138 51 | msgid "Window Display" 52 | msgstr "Afichatge de la fenèstra" 53 | 54 | #: tilda.glade:169 55 | msgid "Audible Terminal Bell" 56 | msgstr "Bip sistèma audible" 57 | 58 | #: tilda.glade:182 59 | #, fuzzy 60 | msgid "Cursor Blinks" 61 | msgstr "Especificatz se òc o non lo cursor de tèxte cluqueteja" 62 | 63 | #: tilda.glade:201 64 | msgid "Terminal Display" 65 | msgstr "Afichatge del terminal" 66 | 67 | #: tilda.glade:234 68 | msgid "Enable Antialiasing" 69 | msgstr "Activar l'anticrenelatge" 70 | 71 | #: tilda.glade:247 72 | msgid "Allow Bold Text" 73 | msgstr "Permetre lo tèxte en gras" 74 | 75 | #: tilda.glade:262 76 | msgid "Position of Tabs:" 77 | msgstr "Posicion dels onglets :" 78 | 79 | #: tilda.glade:275 tilda.glade:1084 80 | #, fuzzy 81 | msgid "" 82 | "Top\n" 83 | "Bottom\n" 84 | "Left\n" 85 | "Right" 86 | msgstr "" 87 | "L'orientacion del tablèu de bòrd. Las quatre valors possiblas son : « top " 88 | "» (naut), « bottom » (bas), « left » (esquèrra) e « right » (drecha). En " 89 | "mòde espandit, la clau indica sus quin costat de l'ecran plaçar lo tablèu " 90 | "de bòrd. En mòde pas espandit, la diferéncia entre « top » e « bottom » es " 91 | "mens importanta - los dos indican qu'es un tablèu de bòrd orizontal - mas " 92 | "dona çaquelà una indicacion utila sul biais que certans elements de tablèu " 93 | "de bòrd se devon comportar. Per exemple, sus un tablèu de bòrd « top », un " 94 | "boton de menú aficha lo menú jol tablèu de bòrd, mentre qu'amb un tablèu " 95 | "de bòrd « bottom » lo menú es afichat en dessús del tablèu de bòrd." 96 | 97 | #: tilda.glade:315 98 | msgid "Font:" 99 | msgstr "Poliça :" 100 | 101 | #: tilda.glade:334 102 | msgid "Font" 103 | msgstr "Poliça" 104 | 105 | #: tilda.glade:358 106 | msgid "General" 107 | msgstr "General" 108 | 109 | #: tilda.glade:404 110 | msgid "Web Browser" 111 | msgstr "Navegadors Web" 112 | 113 | #: tilda.glade:419 114 | msgid "URL Handling" 115 | msgstr "Gestion de las URL" 116 | 117 | #: tilda.glade:451 118 | msgid "Initial Title:" 119 | msgstr "Títol inicial :" 120 | 121 | #: tilda.glade:461 122 | #, fuzzy 123 | msgid "Dynamically-set Title:" 124 | msgstr "Títol modificat _dinamicament :" 125 | 126 | #: tilda.glade:484 127 | msgid "" 128 | "Isn't displayed\n" 129 | "Goes after initial title\n" 130 | "Goes before initial title\n" 131 | "Replace initial title" 132 | msgstr "" 133 | 134 | #: tilda.glade:505 135 | msgid "Title" 136 | msgstr "Títol" 137 | 138 | #: tilda.glade:538 139 | #, fuzzy 140 | msgid "Run a custom command instead of the shell" 141 | msgstr "" 142 | "Indica se cal executar una comanda personalizada a la plaça del shell" 143 | 144 | #: tilda.glade:550 145 | msgid "Custom Command:" 146 | msgstr "Comanda personalizada :" 147 | 148 | #: tilda.glade:562 149 | msgid "When Command Exits:" 150 | msgstr "Quand la comanda sortís :" 151 | 152 | #: tilda.glade:574 153 | msgid "" 154 | "Hold the terminal open\n" 155 | "Restart the command\n" 156 | "Exit the terminal" 157 | msgstr "" 158 | 159 | #: tilda.glade:607 160 | msgid "Command" 161 | msgstr "Comanda" 162 | 163 | #: tilda.glade:632 164 | msgid "Title and Command" 165 | msgstr "Títol e comanda" 166 | 167 | #: tilda.glade:662 tilda.glade:748 168 | msgid "Percentage" 169 | msgstr "Percentatge" 170 | 171 | #: tilda.glade:687 tilda.glade:759 172 | msgid "In Pixels" 173 | msgstr "en pixèls" 174 | 175 | #: tilda.glade:718 176 | msgid "Height" 177 | msgstr "Nautor" 178 | 179 | #: tilda.glade:804 180 | msgid "Width" 181 | msgstr "Largor" 182 | 183 | #: tilda.glade:836 184 | msgid "Centered Horizontally" 185 | msgstr "Centrat orizontalament" 186 | 187 | #: tilda.glade:852 188 | msgid "Centered Vertically" 189 | msgstr "Centrar verticalament" 190 | 191 | #: tilda.glade:869 src/tilda.c:310 192 | msgid "X Position" 193 | msgstr "Posicion X" 194 | 195 | #: tilda.glade:882 src/tilda.c:311 196 | msgid "Y Position" 197 | msgstr "Posicion Y" 198 | 199 | #: tilda.glade:933 200 | msgid "Position" 201 | msgstr "Posicion" 202 | 203 | #: tilda.glade:968 204 | msgid "Enable Transparency" 205 | msgstr "Activar la transparéncia" 206 | 207 | #: tilda.glade:981 208 | #, fuzzy 209 | msgid "Level of Transparency" 210 | msgstr "Nivèl que la plena transparéncia deu representar" 211 | 212 | #: tilda.glade:1008 213 | msgid "Animated Pulldown" 214 | msgstr "Menú animat" 215 | 216 | #: tilda.glade:1023 217 | msgid "Use Image for Background" 218 | msgstr "Utilizar coma imatge de fons" 219 | 220 | #: tilda.glade:1038 221 | msgid "Animation Delay (usec)" 222 | msgstr "Delai animacion (usec)" 223 | 224 | #: tilda.glade:1053 225 | msgid "Animation Orientation" 226 | msgstr "Orientacion animacion" 227 | 228 | #: tilda.glade:1120 229 | msgid "Extras" 230 | msgstr "Demai" 231 | 232 | #: tilda.glade:1145 233 | msgid "Appearance" 234 | msgstr "Aparéncia" 235 | 236 | #: tilda.glade:1187 237 | msgid "Built-in Schemes" 238 | msgstr "Esquèmas predefinits" 239 | 240 | #: tilda.glade:1197 241 | msgid "" 242 | "Custom\n" 243 | "Green on Black\n" 244 | "Black on White\n" 245 | "White on Black" 246 | msgstr "" 247 | 248 | #: tilda.glade:1212 249 | msgid "Text Color" 250 | msgstr "Color de tèxt" 251 | 252 | #: tilda.glade:1224 253 | msgid "Background Color" 254 | msgstr "Color de fons" 255 | 256 | #: tilda.glade:1270 257 | msgid "Foreground and Background Colors" 258 | msgstr "Colors de primièr e rèire plan" 259 | 260 | #: tilda.glade:1293 261 | msgid "Colors" 262 | msgstr "Colors" 263 | 264 | #: tilda.glade:1323 265 | #, fuzzy 266 | msgid "Scroll on Output" 267 | msgstr "Desfilament sus la sortida" 268 | 269 | #: tilda.glade:1338 270 | #, fuzzy 271 | msgid "Scroll on Keystroke" 272 | msgstr "Desfilament sus pression d'una tòca" 273 | 274 | #: tilda.glade:1353 275 | msgid "Scroll Background" 276 | msgstr "Fons de la bara de desfilament" 277 | 278 | #: tilda.glade:1381 279 | msgid "lines" 280 | msgstr "linhas" 281 | 282 | #: tilda.glade:1399 283 | msgid "" 284 | "On the Left\n" 285 | "On the Right\n" 286 | "Disabled" 287 | msgstr "" 288 | "A man esquèrra\n" 289 | "A man drecha\n" 290 | "Desactivat" 291 | 292 | #: tilda.glade:1413 293 | msgid "Scrollback:" 294 | msgstr "" 295 | 296 | #: tilda.glade:1426 297 | msgid "Scrollbar is:" 298 | msgstr "La barra de desfilament es :" 299 | 300 | #: tilda.glade:1441 301 | msgid "Scrolling" 302 | msgstr "Desfilament" 303 | 304 | #: tilda.glade:1464 305 | msgid "Scrolling" 306 | msgstr "Desfilament" 307 | 308 | #: tilda.glade:1482 309 | msgid "Compatibility" 310 | msgstr "Compatibilitat" 311 | 312 | #: tilda.glade:1496 313 | msgid " " 314 | msgstr " " 315 | 316 | #: tilda.glade:1512 317 | msgid "" 318 | "Note: These options may cause some applications to behave " 319 | "incorrectly. They are only here to allow you to work around certain " 320 | "applications and operating systems that expect different terminal behavior." 321 | "" 322 | msgstr "" 323 | 324 | #: tilda.glade:1531 325 | msgid "_Delete key generates:" 326 | msgstr "La tòca _Suprimir fa :" 327 | 328 | #: tilda.glade:1546 329 | msgid "_Backspace key generates:" 330 | msgstr "La tòca « _Retorn arrièr » fa :" 331 | 332 | #: tilda.glade:1558 tilda.glade:1571 333 | msgid "" 334 | "ASCII DEL\n" 335 | "Escape sequence\n" 336 | "Control-H" 337 | msgstr "" 338 | 339 | #: tilda.glade:1599 340 | #, fuzzy 341 | msgid "_Reset Compatibility Options to Defaults" 342 | msgstr "Reïn_icializar las opcions de compatibilitat a las valors per defaut" 343 | 344 | #: tilda.glade:1630 345 | msgid "Compatibility" 346 | msgstr "Compatibilitat" 347 | 348 | #: tilda.glade:1660 349 | msgid "Key Binding" 350 | msgstr "Acorchi" 351 | 352 | #: tilda.glade:1683 353 | msgid "Grab Keybinding" 354 | msgstr "" 355 | 356 | #: tilda.glade:1702 357 | msgid "Pulldown Key" 358 | msgstr "Tòca menú desplegable" 359 | 360 | #: tilda.glade:1725 361 | msgid "Keybindings" 362 | msgstr "Acorchis de clavièr" 363 | 364 | #: tilda.glade:1750 365 | msgid "gtk-close" 366 | msgstr "gtk-close" 367 | 368 | #: src/callback_func.c:53 369 | msgid "Untitled" 370 | msgstr "Sens títol" 371 | 372 | #: src/callback_func.c:71 373 | msgid "Bad value for \"d_set_title\" in config file\n" 374 | msgstr "" 375 | 376 | #: src/configsys.c:128 377 | msgid "Problem parsing config file\n" 378 | msgstr "Error en analisant la sintaxi del fichièr de configuracion\n" 379 | 380 | #: src/configsys.c:249 381 | #, fuzzy 382 | msgid "Unable to sync the config file to disk\n" 383 | msgstr "Impossible de legir lo fichièr de configuracion %s" 384 | 385 | #: src/configsys.c:259 386 | #, fuzzy 387 | msgid "Unable to close the config file\n" 388 | msgstr "Impossible de legir lo fichièr de configuracion %s" 389 | 390 | #: src/configsys.c:268 391 | #, fuzzy, c-format 392 | msgid "Unable to write the config file to %s\n" 393 | msgstr "Impossible de legir lo fichièr de configuracion %s" 394 | 395 | #: src/tilda.c:214 396 | #, fuzzy, c-format 397 | msgid "Unable to run command: `%s'\n" 398 | msgstr "incapable d'aviar %s" 399 | 400 | #: src/tilda.c:237 src/tilda.c:460 401 | #, fuzzy, c-format 402 | msgid "Unable to open lock directory: %s\n" 403 | msgstr "impossible de dobrir lo repertòri « %s »" 404 | 405 | #: src/tilda.c:300 406 | #, fuzzy 407 | msgid "Use Antialiased Fonts" 408 | msgstr "" 409 | "Utilizar de poliças personalizadas per afichar lo corrièr electronic." 410 | 411 | #: src/tilda.c:301 412 | msgid "Set the background color" 413 | msgstr "Definir la color de fons" 414 | 415 | #: src/tilda.c:302 416 | msgid "Run a command at startup" 417 | msgstr "Comanda d'executar al lançament" 418 | 419 | #: src/tilda.c:304 420 | msgid "Set the font to the following string" 421 | msgstr "Definir la poliça utilizada per representar aquesta cadena de tèxt" 422 | 423 | #: src/tilda.c:305 424 | #, fuzzy 425 | msgid "Scrollback Lines" 426 | msgstr "" 427 | "Nombre de linhas de desfilament de conservar. Podètz remontar dins " 428 | "l'istoric del desfilament d'aqueste nombre de linhas ; las linhas que " 429 | "depassan aqueste nombre son escafadas. Se « scrollback-unlimited » es " 430 | "verai, aquesta valor es ignorada." 431 | 432 | #: src/tilda.c:306 433 | msgid "Use Scrollbar" 434 | msgstr "Utilizar la barra de desfilament" 435 | 436 | #: src/tilda.c:307 437 | msgid "Opaqueness: 0-100%" 438 | msgstr "Opacitat : 0-100%" 439 | 440 | #: src/tilda.c:308 441 | msgid "Print the version, then exit" 442 | msgstr "Imprimir la version e quitar" 443 | 444 | #: src/tilda.c:309 445 | msgid "Set Initial Working Directory" 446 | msgstr "Definir lo repertòri de trabalh inicial" 447 | 448 | #: src/tilda.c:312 449 | msgid "Set Background Image" 450 | msgstr "Definir l'imatge de fons" 451 | 452 | #: src/tilda.c:313 453 | msgid "Show Configuration Wizard" 454 | msgstr "Afichar l'assistent de configuracion" 455 | 456 | #: src/tilda.c:329 457 | #, c-format 458 | msgid "" 459 | "Error parsing command-line options. Try \"tilda --help\"\n" 460 | "to see all possible options.\n" 461 | "\n" 462 | "Error message: %s\n" 463 | msgstr "" 464 | 465 | #: src/tilda_terminal.c:386 466 | #, c-format 467 | msgid "Problem parsing custom command: %s\n" 468 | msgstr "Problèma al moment de l'analisi de la comanda personalizada : %s\n" 469 | 470 | #: src/tilda_terminal.c:387 src/tilda_terminal.c:404 471 | #, fuzzy 472 | msgid "Launching default shell instead\n" 473 | msgstr "Executar una comanda personalizada a la plaça de mon shell" 474 | 475 | #: src/tilda_terminal.c:403 476 | #, c-format 477 | msgid "Unable to launch custom command: %s\n" 478 | msgstr "Impossible d'aviar la comanda personalizada : %s\n" 479 | 480 | #: src/tilda_terminal.c:428 481 | #, fuzzy, c-format 482 | msgid "Unable to launch default shell: %s\n" 483 | msgstr "Impossible d'aviar « %s » :" 484 | 485 | #: src/tilda_terminal.c:675 486 | msgid "_New Tab" 487 | msgstr "_Onglet novèl" 488 | 489 | #: src/tilda_terminal.c:679 490 | msgid "_Close Tab" 491 | msgstr "_Tampar l'onglet" 492 | 493 | #: src/tilda_terminal.c:769 494 | #, c-format 495 | msgid "Failed to launch the web browser. The command was `%s'\n" 496 | msgstr "" 497 | 498 | #: src/tilda_window.c:99 499 | msgid "You have a bad tab_pos in your configuration file\n" 500 | msgstr "" 501 | 502 | #: src/tilda_window.c:333 503 | #, c-format 504 | msgid "Unable to set tilda's icon: %s\n" 505 | msgstr "" 506 | 507 | #: src/tilda_window.c:480 508 | msgid "Out of memory, cannot create tab\n" 509 | msgstr "" 510 | 511 | #: src/wizard.c:180 512 | msgid "The keybinding you chose is invalid. Please choose another." 513 | msgstr "" 514 | 515 | #: src/wizard.c:445 516 | msgid "Invalid tab position setting, ignoring\n" 517 | msgstr "" 518 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | # vim: set noexpandtab ts=8 sts=8 sw=8: 2 | 3 | NULL = 4 | 5 | bin_PROGRAMS += src/tilda 6 | 7 | # Rules to compile resources 8 | src/glade-resources.h: src/glade-resources.gresource.xml 9 | $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --generate $< --target=$@ --sourcedir=$(srcdir)/src 10 | src/glade-resources.c: src/glade-resources.gresource.xml 11 | $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --generate $< --target=$@ --sourcedir=$(srcdir)/src 12 | 13 | # Dependencies rule, and do not forget to do a make after 14 | # editing the UI with glade! 15 | src/glade-resources.c src/glade-resources.h: \ 16 | src/glade-resources.gresource.xml \ 17 | $(shell $(GLIB_COMPILE_RESOURCES) --generate-dependencies $(srcdir)/src/glade-resources.gresource.xml --sourcedir=$(srcdir)/src) 18 | 19 | ENUM_TYPES = \ 20 | $(srcdir)/src/tilda-search-box.h \ 21 | $(NULL) 22 | 23 | src/tilda-enum-types.h: $(srcdir)/src/tilda-enum-types.h.template $(ENUM_TYPES) $(GLIB_MKENUMS) 24 | $(AM_V_GEN) ($(GLIB_MKENUMS) --template $(srcdir)/src/tilda-enum-types.h.template $(ENUM_TYPES)) > $@ 25 | 26 | src/tilda-enum-types.c: $(srcdir)/src/tilda-enum-types.c.template $(ENUM_TYPES) $(GLIB_MKENUMS) 27 | $(AM_V_GEN) ($(GLIB_MKENUMS) --template $(srcdir)/src/tilda-enum-types.c.template $(ENUM_TYPES)) > $@ 28 | 29 | GDBUS_CODEGEN_OPTIONS = \ 30 | --interface-prefix 'com.github.lanoxx.tilda.' --c-namespace TildaDbus 31 | 32 | GDBUS_CODEGEN_BODY_OPTIONS = \ 33 | ${GDBUS_CODEGEN_OPTIONS} --body --output $@ 34 | 35 | GDBUS_CODEGEN_HEADER_OPTIONS = \ 36 | ${GDBUS_CODEGEN_OPTIONS} --header --output $@ 37 | 38 | src/tilda-dbus.c: $(srcdir)/src/tilda-dbus-actions.xml $(GDBUS_CODEGEN) 39 | $(AM_V_GEN) $(GDBUS_CODEGEN) $(GDBUS_CODEGEN_BODY_OPTIONS) $(srcdir)/src/tilda-dbus-actions.xml 40 | 41 | src/tilda-dbus.h: ${srcdir}/src/tilda-dbus-actions.xml $(GDBUS_CODEGEN) 42 | $(AM_V_GEN) $(GDBUS_CODEGEN) $(GDBUS_CODEGEN_HEADER_OPTIONS) $(srcdir)/src/tilda-dbus-actions.xml 43 | 44 | src_tilda_CPPFLAGS = \ 45 | $(AM_CPPFLAGS) \ 46 | -I$(top_builddir)/src \ 47 | -DG_LOG_DOMAIN='"tilda"' \ 48 | -DG_LOG_USE_STRUCTURED \ 49 | -DDATADIR='"$(datadir)"' \ 50 | -DLOCALEDIR='"$(localedir)"' \ 51 | -DPKGDATADIR='"$(pkgdatadir)"' \ 52 | $(NULL) 53 | 54 | BUILT_SOURCES = \ 55 | src/glade-resources.h src/glade-resources.c \ 56 | src/tilda-enum-types.c src/tilda-enum-types.h \ 57 | src/tilda-dbus.c src/tilda-dbus.h \ 58 | $(NULL) 59 | 60 | # Keep the headers here so that make dist-bzip2 works 61 | src_tilda_SOURCES = \ 62 | $(BUILT_SOURCES) \ 63 | src/configsys.h src/configsys.c \ 64 | src/debug.h \ 65 | src/eggaccelerators.h src/eggaccelerators.c \ 66 | src/key_grabber.h src/key_grabber.c \ 67 | src/screen-size.h src/screen-size.c \ 68 | src/tilda.h src/tilda.c \ 69 | src/tilda-dbus-actions.h src/tilda-dbus-actions.c \ 70 | src/tilda-keybinding.c src/tilda-keybinding.h \ 71 | src/tilda-lock-files.c src/tilda-lock-files.h \ 72 | src/tilda-cli-options.c src/tilda-cli-options.h \ 73 | src/tilda-context-menu.c src/tilda-context-menu.h \ 74 | src/tilda-match-registry.c src/tilda-match-registry.h \ 75 | src/tilda-palettes.h src/tilda-palettes.c \ 76 | src/tilda-regex.h \ 77 | src/tilda-search-box.c src/tilda-search-box.h \ 78 | src/tilda_terminal.h src/tilda_terminal.c \ 79 | src/tilda-url-spawner.h src/tilda-url-spawner.c \ 80 | src/tilda_window.h src/tilda_window.c \ 81 | src/tomboykeybinder.h src/tomboykeybinder.c \ 82 | src/wizard.h src/wizard.c \ 83 | $(NULL) 84 | 85 | src_tilda_CFLAGS = \ 86 | $(AM_CFLAGS) \ 87 | $(GTK_CFLAGS) \ 88 | $(LIBGLADE_CFLAGS) \ 89 | $(VTE_CFLAGS) \ 90 | $(LIBCONFUSE_CFLAGS) \ 91 | $(X11_CFLAGS) \ 92 | $(NULL) 93 | 94 | src_tilda_LDFLAGS = \ 95 | $(AM_LDFLAGS) \ 96 | $(GTK_LDFLAGS) \ 97 | $(LIBGLADE_LDFLAGS) \ 98 | $(VTE_LDFLAGS) \ 99 | $(LIBCONFUSE_LDFLAGS) \ 100 | $(X11_LDFLAGS) \ 101 | -Wl,--as-needed \ 102 | $(NULL) 103 | 104 | src_tilda_LDADD = \ 105 | $(AM_LDADD) \ 106 | $(GTK_LIBS) \ 107 | $(LIBGLADE_LIBS) \ 108 | $(VTE_LIBS) \ 109 | $(LIBCONFUSE_LIBS) \ 110 | $(X11_LIBS) \ 111 | $(LTLIBINTL) \ 112 | $(LEXLIB) \ 113 | -lm \ 114 | $(NULL) 115 | 116 | EXTRA_DIST += \ 117 | src/glade-resources.gresource.xml \ 118 | src/tilda-dbus-actions.xml \ 119 | src/tilda-search-box.ui \ 120 | src/tilda.ui \ 121 | src/tilda-enum-types.h.template \ 122 | src/tilda-enum-types.c.template \ 123 | $(NULL) 124 | 125 | CLEANFILES += \ 126 | src/glade-resources.h \ 127 | src/glade-resources.c \ 128 | src/tilda-enum-types.h \ 129 | src/tilda-enum-types.c \ 130 | src/tilda-dbus.c \ 131 | src/tilda-dbus.h \ 132 | $(NULL) 133 | -------------------------------------------------------------------------------- /src/configsys.h: -------------------------------------------------------------------------------- 1 | /* vim: set ts=8 sts=8 sw=8 noexpandtab textwidth=112: */ 2 | /* 3 | * This is free software; you can redistribute it and/or modify it under 4 | * the terms of the GNU Library General Public License as published by 5 | * the Free Software Foundation; either version 2 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * This program is distributed in the hope that it will be useful, but 9 | * WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | * General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU Library General Public 14 | * License along with this library. If not, see . 15 | */ 16 | 17 | #ifndef CONFIGSYS_H 18 | #define CONFIGSYS_H 19 | 20 | #include 21 | #include 22 | 23 | #define DEFAULT_WORD_CHARS "-A-Za-z0-9,./?%&#:_" 24 | 25 | /** 26 | * Computes the size of pixels relative to max_pixels and 27 | * returns them as a ratio with a range of 0 to 1. 28 | */ 29 | #define pixels_absolute_to_ratio(max_pixels, pixels) \ 30 | (((gdouble) pixels) / ((gdouble) max_pixels)) 31 | 32 | /** 33 | * Computes the absolute number of pixels given a ratio with a range 34 | * of 0 to 1 and a size. 35 | */ 36 | #define pixels_ratio_to_absolute(ratio, size) \ 37 | (gint) ((ratio) * (size)) 38 | 39 | /** 40 | * Macro to convert a long value to a double by scaling it 41 | * with G_MAXINT. 42 | */ 43 | #define GLONG_TO_DOUBLE(value) ((value) / (double) G_MAXINT) 44 | 45 | /** 46 | * Macro to convert a double to a long value by scaling it with G_MAXINT. 47 | */ 48 | #define GLONG_FROM_DOUBLE(value) ((long) ((value) * G_MAXINT)) 49 | 50 | /* Initialize and free the config system's private variables */ 51 | gint config_init (const gchar *config_file); 52 | gint config_free (const gchar *config_file); 53 | 54 | /* Write to disk (generally discouraged) */ 55 | gint config_write (const gchar *config_file); 56 | 57 | /* Set values in the config system */ 58 | gint config_setint (const gchar *key, const glong val); 59 | gint config_setstr (const gchar *key, const gchar *val); 60 | gint config_setbool (const gchar *key, const gboolean val); 61 | gint config_setnint (const gchar *key, const glong val, const guint idx); 62 | 63 | /* Get values from the config system */ 64 | glong config_getint (const gchar *key); 65 | gchar* config_getstr (const gchar *key); 66 | gboolean config_getbool (const gchar *key); 67 | glong config_getnint (const gchar *key, const guint idx); 68 | 69 | /** 70 | * This function uses the configured relative ratio of the window size and 71 | * applies it to the current workarea size to compute the desired absolute 72 | * size in pixels. 73 | * 74 | * @param rectangle A GdkRectangle with the configured window size in pixes. 75 | */ 76 | void config_get_configured_window_size (GdkRectangle *rectangle); 77 | 78 | #endif /* CONFIGSYS_H */ 79 | 80 | -------------------------------------------------------------------------------- /src/debug.h: -------------------------------------------------------------------------------- 1 | /* vim: set ts=4 sts=4 sw=4 expandtab textwidth=92: */ 2 | /* 3 | * This is free software; you can redistribute it and/or modify it under 4 | * the terms of the GNU Library General Public License as published by 5 | * the Free Software Foundation; either version 2 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * This program is distributed in the hope that it will be useful, but 9 | * WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | * General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU Library General Public 14 | * License along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 16 | */ 17 | 18 | #ifndef DEBUG_H 19 | #define DEBUG_H 20 | 21 | #include "config.h" 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | /* Debug Macros 28 | * 29 | * Add -DDEBUG to your compile options to turn on assert()s. 30 | * 31 | * If you do not have the DEBUG symbol defined, then asserts will 32 | * be turned off and compiled into a noop. 33 | */ 34 | 35 | #if DEBUG 36 | /* Enable asserts */ 37 | #undef NDEBUG 38 | #include 39 | 40 | #define DEBUG_ASSERT assert 41 | 42 | #define DEBUG_ERROR(ERRMSG) g_printerr("*** DEVELOPER ERROR *** at %s:%d" \ 43 | " -> %s\n", __FILE__, __LINE__, (ERRMSG)) 44 | 45 | #else 46 | 47 | /* Disable asserts */ 48 | #define NDEBUG 49 | #include 50 | 51 | #define DEBUG_ASSERT assert 52 | 53 | #define DEBUG_ERROR(ERRMSG) {} 54 | 55 | #endif 56 | 57 | /* Function tracing 58 | * 59 | * Add -DDEBUG_FUNCTIONS to your compile options to turn on function tracing. 60 | * 61 | * If you do not have the DEBUG_FUNCTIONS symbol defined, then function tracing will 62 | * be turned off and compiled into a noop. 63 | */ 64 | 65 | #if DEBUG_FUNCTIONS 66 | 67 | #define DEBUG_FUNCTION(NAME) g_debug("%s: FUNCTION ENTERED: %s", basename(__FILE__), (NAME)) 68 | 69 | #define DEBUG_FUNCTION_MESSAGE(NAME,FORMAT,args...) { \ 70 | gchar *message = g_strdup_printf ((FORMAT), ##args); \ 71 | g_debug("%s: FUNCTION ENTERED: %s: %s", basename(__FILE__), (NAME), message); \ 72 | g_free (message); \ 73 | } 74 | 75 | #else 76 | 77 | #define DEBUG_FUNCTION(NAME) {} 78 | 79 | #define DEBUG_FUNCTION_MESSAGE(NAME,FORMAT,args...) {} 80 | 81 | #endif 82 | 83 | /* A macro that calls perror() with a consistent header string */ 84 | #define TILDA_PERROR() perror("Tilda encountered an error") 85 | 86 | #endif /* DEBUG_H */ 87 | 88 | -------------------------------------------------------------------------------- /src/eggaccelerators.c: -------------------------------------------------------------------------------- 1 | /* vim: set ts=4 sts=4 sw=4 expandtab: */ 2 | /* eggaccelerators.c 3 | * Copyright (C) 2002 Red Hat, Inc.; Copyright 1998, 2001 Tim Janik 4 | * Developed by Havoc Pennington, Tim Janik 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Library General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Library General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Library General Public 17 | * License along with this library. If not, see . 18 | */ 19 | 20 | #include "eggaccelerators.h" 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | enum { 27 | EGG_MODMAP_ENTRY_SHIFT = 0, 28 | EGG_MODMAP_ENTRY_LOCK = 1, 29 | EGG_MODMAP_ENTRY_CONTROL = 2, 30 | EGG_MODMAP_ENTRY_MOD1 = 3, 31 | EGG_MODMAP_ENTRY_MOD2 = 4, 32 | EGG_MODMAP_ENTRY_MOD3 = 5, 33 | EGG_MODMAP_ENTRY_MOD4 = 6, 34 | EGG_MODMAP_ENTRY_MOD5 = 7, 35 | EGG_MODMAP_ENTRY_LAST = 8 36 | }; 37 | 38 | typedef struct { 39 | EggVirtualModifierType mapping[EGG_MODMAP_ENTRY_LAST]; 40 | } EggModmap; 41 | 42 | const EggModmap* egg_keymap_get_modmap (GdkKeymap *keymap); 43 | 44 | void 45 | egg_keymap_resolve_virtual_modifiers (GdkKeymap *keymap, 46 | EggVirtualModifierType virtual_mods, 47 | GdkModifierType *concrete_mods) 48 | { 49 | GdkModifierType concrete; 50 | int i; 51 | const EggModmap *modmap; 52 | 53 | g_return_if_fail (GDK_IS_KEYMAP (keymap)); 54 | g_return_if_fail (concrete_mods != NULL); 55 | 56 | modmap = egg_keymap_get_modmap (keymap); 57 | 58 | /* Not so sure about this algorithm. */ 59 | 60 | concrete = (GdkModifierType) 0; 61 | i = 0; 62 | while (i < EGG_MODMAP_ENTRY_LAST) 63 | { 64 | if (modmap->mapping[i] & virtual_mods) 65 | concrete |= (1 << i); 66 | 67 | ++i; 68 | } 69 | 70 | *concrete_mods = concrete; 71 | } 72 | 73 | static void 74 | reload_modmap (GdkKeymap *keymap, 75 | EggModmap *modmap) 76 | { 77 | XModifierKeymap *xmodmap; 78 | int map_size; 79 | int i; 80 | 81 | /* FIXME multihead */ 82 | xmodmap = XGetModifierMapping (gdk_x11_get_default_xdisplay ()); 83 | 84 | memset (modmap->mapping, 0, sizeof (modmap->mapping)); 85 | 86 | /* there are 8 modifiers, and the first 3 are shift, shift lock, 87 | * and control 88 | */ 89 | map_size = 8 * xmodmap->max_keypermod; 90 | i = 3 * xmodmap->max_keypermod; 91 | while (i < map_size) { 92 | /* get the key code at this point in the map, 93 | * see if its keysym is one we're interested in 94 | */ 95 | int keycode = xmodmap->modifiermap[i]; 96 | GdkKeymapKey *keys; 97 | guint *keyvals; 98 | int n_entries; 99 | int j; 100 | EggVirtualModifierType mask; 101 | 102 | keys = NULL; 103 | keyvals = NULL; 104 | n_entries = 0; 105 | 106 | gdk_keymap_get_entries_for_keycode (keymap, 107 | keycode, 108 | &keys, &keyvals, &n_entries); 109 | 110 | mask = 0; 111 | j = 0; 112 | while (j < n_entries) { 113 | if (keyvals[j] == GDK_KEY_Num_Lock) 114 | mask |= EGG_VIRTUAL_NUM_LOCK_MASK; 115 | else if (keyvals[j] == GDK_KEY_Scroll_Lock) 116 | mask |= EGG_VIRTUAL_SCROLL_LOCK_MASK; 117 | else if (keyvals[j] == GDK_KEY_Meta_L || 118 | keyvals[j] == GDK_KEY_Meta_R) 119 | mask |= EGG_VIRTUAL_META_MASK; 120 | else if (keyvals[j] == GDK_KEY_Hyper_L || 121 | keyvals[j] == GDK_KEY_Hyper_R) 122 | mask |= EGG_VIRTUAL_HYPER_MASK; 123 | else if (keyvals[j] == GDK_KEY_Super_L || 124 | keyvals[j] == GDK_KEY_Super_R) 125 | mask |= EGG_VIRTUAL_SUPER_MASK; 126 | else if (keyvals[j] == GDK_KEY_Mode_switch) 127 | mask |= EGG_VIRTUAL_MODE_SWITCH_MASK; 128 | 129 | ++j; 130 | } 131 | 132 | /* Mod1Mask is 1 << 3 for example, i.e. the 133 | * fourth modifier, i / keyspermod is the modifier 134 | * index 135 | */ 136 | modmap->mapping[i/xmodmap->max_keypermod] |= mask; 137 | 138 | g_free (keyvals); 139 | g_free (keys); 140 | 141 | ++i; 142 | } 143 | 144 | /* Add in the not-really-virtual fixed entries */ 145 | modmap->mapping[EGG_MODMAP_ENTRY_SHIFT] |= EGG_VIRTUAL_SHIFT_MASK; 146 | modmap->mapping[EGG_MODMAP_ENTRY_CONTROL] |= EGG_VIRTUAL_CONTROL_MASK; 147 | modmap->mapping[EGG_MODMAP_ENTRY_LOCK] |= EGG_VIRTUAL_LOCK_MASK; 148 | modmap->mapping[EGG_MODMAP_ENTRY_MOD1] |= EGG_VIRTUAL_ALT_MASK; 149 | modmap->mapping[EGG_MODMAP_ENTRY_MOD2] |= EGG_VIRTUAL_MOD2_MASK; 150 | modmap->mapping[EGG_MODMAP_ENTRY_MOD3] |= EGG_VIRTUAL_MOD3_MASK; 151 | modmap->mapping[EGG_MODMAP_ENTRY_MOD4] |= EGG_VIRTUAL_MOD4_MASK; 152 | modmap->mapping[EGG_MODMAP_ENTRY_MOD5] |= EGG_VIRTUAL_MOD5_MASK; 153 | 154 | XFreeModifiermap (xmodmap); 155 | } 156 | 157 | const EggModmap* 158 | egg_keymap_get_modmap (GdkKeymap *keymap) { 159 | EggModmap *modmap; 160 | 161 | /* This is all a hack, much simpler when we can just 162 | * modify GDK directly. 163 | */ 164 | modmap = g_object_get_data (G_OBJECT (keymap), 165 | "egg-modmap"); 166 | 167 | if (modmap == NULL) { 168 | modmap = g_new0 (EggModmap, 1); 169 | 170 | /* FIXME modify keymap change events with an event filter 171 | * and force a reload if we get one 172 | */ 173 | reload_modmap (keymap, modmap); 174 | g_object_set_data_full (G_OBJECT (keymap), 175 | "egg-modmap", 176 | modmap, 177 | g_free); 178 | } 179 | 180 | g_assert (modmap != NULL); 181 | return modmap; 182 | } 183 | -------------------------------------------------------------------------------- /src/eggaccelerators.h: -------------------------------------------------------------------------------- 1 | /* eggaccelerators.h 2 | * Copyright (C) 2002 Red Hat, Inc. 3 | * Developed by Havoc Pennington 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Library General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Library General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Library General Public 16 | * License along with this library. If not, see . 17 | */ 18 | 19 | #ifndef __EGG_ACCELERATORS_H__ 20 | #define __EGG_ACCELERATORS_H__ 21 | 22 | #include 23 | 24 | G_BEGIN_DECLS 25 | 26 | /* Where a value is also in GdkModifierType we coincide, 27 | * otherwise we don't overlap. 28 | */ 29 | typedef enum { 30 | EGG_VIRTUAL_SHIFT_MASK = 1 << 0, 31 | EGG_VIRTUAL_LOCK_MASK = 1 << 1, 32 | EGG_VIRTUAL_CONTROL_MASK = 1 << 2, 33 | 34 | EGG_VIRTUAL_ALT_MASK = 1 << 3, /* fixed as Mod1 */ 35 | 36 | EGG_VIRTUAL_MOD2_MASK = 1 << 4, 37 | EGG_VIRTUAL_MOD3_MASK = 1 << 5, 38 | EGG_VIRTUAL_MOD4_MASK = 1 << 6, 39 | EGG_VIRTUAL_MOD5_MASK = 1 << 7, 40 | 41 | #if 0 42 | GDK_BUTTON1_MASK = 1 << 8, 43 | GDK_BUTTON2_MASK = 1 << 9, 44 | GDK_BUTTON3_MASK = 1 << 10, 45 | GDK_BUTTON4_MASK = 1 << 11, 46 | GDK_BUTTON5_MASK = 1 << 12, 47 | /* 13, 14 are used by Xkb for the keyboard group */ 48 | #endif 49 | 50 | EGG_VIRTUAL_META_MASK = 1 << 24, 51 | EGG_VIRTUAL_SUPER_MASK = 1 << 25, 52 | EGG_VIRTUAL_HYPER_MASK = 1 << 26, 53 | EGG_VIRTUAL_MODE_SWITCH_MASK = 1 << 27, 54 | EGG_VIRTUAL_NUM_LOCK_MASK = 1 << 28, 55 | EGG_VIRTUAL_SCROLL_LOCK_MASK = 1 << 29, 56 | 57 | /* Also in GdkModifierType */ 58 | EGG_VIRTUAL_RELEASE_MASK = 1 << 30, 59 | 60 | /* 28-31 24-27 20-23 16-19 12-15 8-11 4-7 0-3 61 | * 7 f 0 0 0 0 f f 62 | */ 63 | EGG_VIRTUAL_MODIFIER_MASK = 0x7f0000ff 64 | 65 | } EggVirtualModifierType; 66 | 67 | void egg_keymap_resolve_virtual_modifiers (GdkKeymap *keymap, 68 | EggVirtualModifierType virtual_mods, 69 | GdkModifierType *concrete_mods); 70 | 71 | G_END_DECLS 72 | 73 | 74 | #endif /* __EGG_ACCELERATORS_H__ */ 75 | -------------------------------------------------------------------------------- /src/glade-resources.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | tilda.ui 5 | tilda-search-box.ui 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/key_grabber.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free software; you can redistribute it and/or modify it under 3 | * the terms of the GNU Library General Public License as published by 4 | * the Free Software Foundation; either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, but 8 | * WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Library General Public 13 | * License along with this library. If not, see . 14 | */ 15 | 16 | #ifndef TILDA_KEY_GRABBER_C 17 | #define TILDA_KEY_GRABBER_C 18 | 19 | #include "tilda_window.h" 20 | 21 | G_BEGIN_DECLS 22 | 23 | void pull (struct tilda_window_ *tw, enum pull_action action, gboolean force_hide); 24 | 25 | extern void generate_animation_positions (tilda_window *tw); 26 | 27 | gboolean tilda_keygrabber_bind (const gchar *keystr, tilda_window *tw); 28 | void tilda_keygrabber_unbind (const gchar *keystr); 29 | 30 | /** 31 | * This function will make the tilda window active after it starts 32 | */ 33 | void tilda_window_set_active (tilda_window *tw); 34 | 35 | G_END_DECLS 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/screen-size.c: -------------------------------------------------------------------------------- 1 | #include "screen-size.h" 2 | 3 | #include 4 | 5 | static gint 6 | get_window_scaling_factor (void) 7 | { 8 | GValue gvalue = G_VALUE_INIT; 9 | GdkScreen *screen; 10 | 11 | g_value_init (&gvalue, G_TYPE_INT); 12 | 13 | screen = gdk_screen_get_default (); 14 | if (gdk_screen_get_setting (screen, "gdk-window-scaling-factor", &gvalue)) 15 | return g_value_get_int (&gvalue); 16 | 17 | return 1; 18 | } 19 | 20 | void 21 | screen_size_get_dimensions (gint *width, 22 | gint *height) 23 | { 24 | GdkScreen *screen; 25 | GdkWindow *window; 26 | gint scale; 27 | 28 | scale = get_window_scaling_factor (); 29 | 30 | screen = gdk_screen_get_default (); 31 | window = gdk_screen_get_root_window (screen); 32 | 33 | *width = gdk_window_get_width (window) / scale; 34 | *height = gdk_window_get_height (window) / scale; 35 | } 36 | -------------------------------------------------------------------------------- /src/screen-size.h: -------------------------------------------------------------------------------- 1 | #ifndef TILDA_SCREEN_SIZE_H 2 | #define TILDA_SCREEN_SIZE_H 3 | 4 | #include 5 | 6 | void screen_size_get_dimensions (gint *width, 7 | gint *height); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/tilda-cli-options.c: -------------------------------------------------------------------------------- 1 | #include "tilda-cli-options.h" 2 | 3 | #include "config.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "debug.h" 10 | 11 | static GQuark tilda_error_quark (void); 12 | 13 | G_DEFINE_QUARK(tilda-config-error-quark, tilda_error) 14 | 15 | typedef enum { 16 | TILDA_CONFIG_ERROR_BAD_INPUT, // Error for bad config argument 17 | } TildaConfigError; 18 | 19 | static gboolean toggle_option_cb (const gchar *option_name, 20 | const gchar *value, 21 | gpointer user_data, 22 | GError **error); 23 | 24 | gboolean tilda_cli_options_parse_options (tilda_cli_options *cli_options, 25 | gint argc, 26 | gchar *argv[], 27 | gchar **config_file) 28 | { 29 | DEBUG_FUNCTION ("parse_cli"); 30 | DEBUG_ASSERT (argc != 0); 31 | DEBUG_ASSERT (argv != NULL); 32 | // *config_file must be non-null only if a configuration file path has been parsed 33 | DEBUG_ASSERT (*config_file == NULL); 34 | 35 | /* All tilda command-line options */ 36 | GOptionEntry cl_opts[] = { 37 | { "background-color", 'b', 0, G_OPTION_ARG_STRING, &(cli_options->background_color), N_("Set the background color"), NULL }, 38 | { "command", 'c', 0, G_OPTION_ARG_STRING, &(cli_options->command), N_("Run a command at startup"), NULL }, 39 | { "hidden", 'h', 0, G_OPTION_ARG_NONE, &(cli_options->hidden), N_("Start Tilda hidden"), NULL }, 40 | { "font", 'f', 0, G_OPTION_ARG_STRING, &(cli_options->font), N_("Set the font to the following string"), NULL }, 41 | { "config-file", 'g', 0, G_OPTION_ARG_STRING, config_file, N_("Configuration file"), NULL }, 42 | { "lines", 'l', 0, G_OPTION_ARG_INT, &(cli_options->lines), N_("Scrollback Lines"), NULL }, 43 | { "scrollbar", 's', 0, G_OPTION_ARG_NONE, &(cli_options->scrollbar), N_("Use Scrollbar"), NULL }, 44 | { "version", 'v', 0, G_OPTION_ARG_NONE, &(cli_options->version), N_("Print the version, then exit"), NULL }, 45 | { "working-dir", 'w', 0, G_OPTION_ARG_STRING, &(cli_options->working_dir), N_("Set Initial Working Directory"), NULL }, 46 | { "x-pos", 'x', 0, G_OPTION_ARG_INT, &(cli_options->x_pos), N_("X Position"), NULL }, 47 | { "y-pos", 'y', 0, G_OPTION_ARG_INT, &(cli_options->y_pos), N_("Y Position"), NULL }, 48 | { "background-alpha", 't', 0, G_OPTION_ARG_INT, &(cli_options->back_alpha), N_("Opaqueness: 0-100%"), NULL }, 49 | { "config", 'C', 0, G_OPTION_ARG_NONE, &(cli_options->show_config), N_("Show Configuration Wizard"), NULL }, 50 | G_OPTION_ENTRY_NULL 51 | }; 52 | 53 | GOptionEntry dbus_opts[] = { 54 | { "dbus", 0, 0, G_OPTION_ARG_NONE, 55 | &(cli_options->enable_dbus), N_("Enable D-Bus interface for this instance"), NULL }, 56 | { "toggle-window", 'T', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, 57 | toggle_option_cb, N_("Toggle N-th instance Window visibility and exit"), NULL 58 | }, 59 | G_OPTION_ENTRY_NULL 60 | }; 61 | 62 | /* Set up the command-line parser */ 63 | GError *error = NULL; 64 | GOptionContext *context = g_option_context_new (NULL); 65 | g_option_context_add_main_entries (context, cl_opts, NULL); 66 | 67 | /* Register a separate group for DBus related options. */ 68 | GOptionGroup *group = g_option_group_new ("dbus", "D-Bus Options:", "Show Tilda D-Bus Options", cli_options, NULL); 69 | g_option_group_add_entries (group, dbus_opts); 70 | g_option_context_add_group (context, group); 71 | 72 | /* Register default GTK and GDK related option group. */ 73 | g_option_context_add_group (context, gtk_get_option_group (FALSE)); 74 | 75 | g_option_context_parse (context, &argc, &argv, &error); 76 | g_option_context_free (context); 77 | 78 | /* Check for unknown options, and give a nice message if there are some */ 79 | if (error) 80 | { 81 | g_printerr (_("Error parsing command-line options. Try \"tilda --help\"\nto see all possible options.\n\nError message: %s\n"), 82 | error->message); 83 | 84 | exit (EXIT_FAILURE); 85 | } 86 | 87 | /* If we need to show the version, show it then exit normally */ 88 | if (cli_options->version) 89 | { 90 | g_print ("%s\n\n", PACKAGE_STRING); 91 | 92 | g_print ("Copyright (c) 2012-2020 Sebastian Geiger (lanoxx@gmx.net)\n"); 93 | g_print ("Copyright (c) 2005-2009 Tristan Sloughter (sloutri@iit.edu)\n"); 94 | g_print ("Copyright (c) 2005-2009 Ira W. Snyder (tilda@irasnyder.com)\n\n"); 95 | 96 | g_print ("General Information: https://github.com/lanoxx/tilda\n"); 97 | g_print ("Bug Reports: https://github.com/lanoxx/tilda/issues?state=open\n\n"); 98 | 99 | g_print ("This program comes with ABSOLUTELY NO WARRANTY.\n"); 100 | g_print ("This is free software, and you are welcome to redistribute it\n"); 101 | g_print ("under certain conditions. See the file COPYING for details.\n"); 102 | 103 | exit (EXIT_SUCCESS); 104 | } 105 | 106 | /* TRUE if we should show the config wizard, FALSE otherwise */ 107 | return cli_options->show_config; 108 | } 109 | 110 | tilda_cli_options *tilda_cli_options_new () 111 | { 112 | tilda_cli_options *options = g_malloc0(sizeof(tilda_cli_options)); 113 | if (!options) 114 | { 115 | g_printerr (_("Error allocating memory for a new tilda_cli_options structure.\n")); 116 | exit (EXIT_FAILURE); 117 | } 118 | 119 | // instance id of the windows will be in range from 0 to N, 120 | // defaults to -1 (unset) if option is not used. 121 | options->toggle_window = -1; 122 | 123 | return options; 124 | } 125 | 126 | /** 127 | * toggle_option_cb: A GOptionArgFunc which parses the toggle-window option 128 | * argument. Using this toggle function allows us to assign a default value, 129 | * if the user just specifies the option without a value. For example, the 130 | * user may use '-T' instead of '-T 0', in this case we set the default 131 | * instance_id to 0. Most users will want to use the default unless they 132 | * are running multiple tilda instances and thus this makes the setup 133 | * of toggle shortcuts easier. 134 | */ 135 | static gboolean toggle_option_cb (G_GNUC_UNUSED const gchar *option_name, 136 | const gchar *value, 137 | gpointer user_data, 138 | GError **error) 139 | { 140 | if (!user_data) { 141 | g_error("Missing user_data pointer in toggle_option_cb function."); 142 | } 143 | 144 | tilda_cli_options *options = user_data; 145 | 146 | if (!value || !value[0]) { 147 | options->toggle_window = 0; 148 | return TRUE; 149 | } 150 | 151 | char * parseEnd = NULL; 152 | 153 | long instance_id = strtol(value, &parseEnd, 10); 154 | 155 | if (parseEnd != NULL && *parseEnd != '\0') { 156 | g_set_error(error, tilda_error_quark(), TILDA_CONFIG_ERROR_BAD_INPUT, "Could not parse the toggle argument. The argument must be a valid integer."); 157 | return FALSE; 158 | } 159 | 160 | // sanity check for (gint) cast below. In practice, there will 161 | // only ever be a few instances running, so this value will probably 162 | // never be higher than 10, but to make the gint cast save, we check 163 | // against INT_MAX 164 | if (instance_id > INT_MAX) { 165 | g_set_error (error, tilda_error_quark(), TILDA_CONFIG_ERROR_BAD_INPUT, 166 | "The toggle window option cannot must not be greater than %d, but value was %ld.", INT_MAX, instance_id); 167 | return FALSE; 168 | } 169 | 170 | // if the user specified a negative value, then we default to 0. 171 | if (instance_id < 0) { 172 | instance_id = 0; 173 | } 174 | 175 | options->toggle_window = (gint) instance_id; 176 | 177 | return TRUE; 178 | } 179 | -------------------------------------------------------------------------------- /src/tilda-cli-options.h: -------------------------------------------------------------------------------- 1 | #ifndef TILDA_OPTIONS_H 2 | #define TILDA_OPTIONS_H 3 | 4 | #include 5 | 6 | typedef struct tilda_cli_options tilda_cli_options; 7 | 8 | struct tilda_cli_options { 9 | gchar *background_color; 10 | gchar *command; 11 | gchar *font; 12 | gchar *working_dir; 13 | gint toggle_window; 14 | gint back_alpha; 15 | gint lines; 16 | gint x_pos; 17 | gint y_pos; 18 | gboolean scrollbar; 19 | gboolean show_config; 20 | gboolean version; 21 | gboolean hidden; 22 | gboolean enable_dbus; 23 | }; 24 | 25 | /** 26 | * Creates a new tilda_cli_option instance. 27 | * 28 | * @return returns 29 | * a pointer to a newly allocated tilda_cli_options structure, we 30 | * should be freed when no longer needed. 31 | */ 32 | tilda_cli_options *tilda_cli_options_new (void); 33 | 34 | /** 35 | * Parse all of the Command-Line Options given to tilda. 36 | * This can modify argv and argc, and will set values in the config. 37 | * 38 | * @param cli_options pointer to a struct to store command-line options into 39 | * @param argc argc from main 40 | * @param argv argv from main 41 | * @param config_file pointer which will be used to store the config file path if it was specified via command-line 42 | * @return TRUE if we should show the configuration wizard, FALSE otherwise 43 | */ 44 | gboolean tilda_cli_options_parse_options (tilda_cli_options *options, 45 | gint argc, 46 | gchar **argv, 47 | gchar **config_file); 48 | 49 | #endif //TILDA_OPTIONS_H 50 | -------------------------------------------------------------------------------- /src/tilda-context-menu.c: -------------------------------------------------------------------------------- 1 | #include "tilda-context-menu.h" 2 | 3 | #include "debug.h" 4 | #include "wizard.h" 5 | #include "tilda-url-spawner.h" 6 | 7 | #include 8 | #include 9 | 10 | typedef struct { 11 | tilda_window * tw; 12 | tilda_term * tt; 13 | char * match; 14 | TildaMatchRegistryEntry * match_entry; 15 | } TildaContextMenu; 16 | 17 | static void 18 | tilda_context_menu_free (TildaContextMenu * context_menu); 19 | 20 | static void 21 | menu_add_tab_cb (GSimpleAction *action, 22 | GVariant *parameter, 23 | gpointer user_data) 24 | { 25 | DEBUG_FUNCTION ("menu_add_tab_cb"); 26 | DEBUG_ASSERT (user_data != NULL); 27 | 28 | tilda_window_add_tab (TILDA_WINDOW (user_data)); 29 | } 30 | 31 | static void 32 | menu_close_tab_cb (GSimpleAction *action, 33 | GVariant *parameter, 34 | gpointer user_data) 35 | { 36 | DEBUG_FUNCTION ("menu_close_tab_cb"); 37 | DEBUG_ASSERT (user_data != NULL); 38 | 39 | tilda_window_close_current_tab (TILDA_WINDOW (user_data)); 40 | } 41 | 42 | static void 43 | menu_copy_cb (GSimpleAction *action, 44 | GVariant *parameter, 45 | gpointer user_data) 46 | { 47 | DEBUG_FUNCTION ("menu_copy_cb"); 48 | DEBUG_ASSERT (user_data != NULL); 49 | 50 | tilda_term *tt = TILDA_TERM (user_data); 51 | 52 | vte_terminal_copy_clipboard_format (VTE_TERMINAL (tt->vte_term), VTE_FORMAT_TEXT); 53 | } 54 | 55 | static void 56 | menu_paste_cb (GSimpleAction *action, 57 | GVariant *parameter, 58 | gpointer user_data) 59 | { 60 | DEBUG_FUNCTION ("menu_paste_cb"); 61 | DEBUG_ASSERT (user_data != NULL); 62 | 63 | tilda_term *tt = TILDA_TERM (user_data); 64 | 65 | vte_terminal_paste_clipboard (VTE_TERMINAL (tt->vte_term)); 66 | } 67 | 68 | static void 69 | menu_copy_match_cb (GSimpleAction * action, 70 | GVariant * parameter, 71 | gpointer user_data) 72 | { 73 | DEBUG_FUNCTION ("menu_copy_match_cb"); 74 | DEBUG_ASSERT (user_data != NULL); 75 | 76 | char * match = user_data; 77 | 78 | GtkClipboard * clipBoard = gtk_clipboard_get_default (gdk_display_get_default ()); 79 | 80 | gtk_clipboard_set_text (clipBoard, match, -1); 81 | } 82 | 83 | static void 84 | menu_open_match_cb (GSimpleAction * action, 85 | GVariant * parameter, 86 | gpointer user_data) 87 | { 88 | DEBUG_FUNCTION("menu_open_match_cb"); 89 | 90 | TildaContextMenu *context_menu = user_data; 91 | GtkWindow * parent; 92 | 93 | parent = GTK_WINDOW (context_menu->tw->window); 94 | 95 | tilda_url_spawner_spawn_browser_for_match (parent, 96 | context_menu->match, 97 | context_menu->match_entry); 98 | } 99 | 100 | static void 101 | menu_fullscreen_cb (GSimpleAction *action, 102 | GVariant *parameter, 103 | gpointer user_data) 104 | { 105 | DEBUG_FUNCTION ("menu_fullscreen_cb"); 106 | DEBUG_ASSERT (user_data != NULL); 107 | 108 | toggle_fullscreen_cb (TILDA_WINDOW (user_data)); 109 | } 110 | 111 | static void 112 | menu_searchbar_cb (GSimpleAction *action, 113 | GVariant *parameter, 114 | gpointer user_data) 115 | { 116 | DEBUG_FUNCTION ("menu_fullscreen_cb"); 117 | DEBUG_ASSERT (user_data != NULL); 118 | 119 | tilda_window_toggle_searchbar (TILDA_WINDOW (user_data)); 120 | } 121 | 122 | static void 123 | menu_preferences_cb (GSimpleAction *action, 124 | GVariant *parameter, 125 | gpointer user_data) 126 | { 127 | DEBUG_FUNCTION ("menu_config_cb"); 128 | DEBUG_ASSERT (user_data != NULL); 129 | 130 | /* Show the config wizard */ 131 | wizard (TILDA_WINDOW (user_data)); 132 | } 133 | 134 | static void 135 | menu_quit_cb (GSimpleAction *action, 136 | GVariant *parameter, 137 | gpointer user_data) 138 | { 139 | DEBUG_FUNCTION ("menu_quit_cb"); 140 | 141 | tilda_window_confirm_quit (TILDA_WINDOW (user_data)); 142 | } 143 | 144 | static void on_popup_hide (GtkWidget *widget, TildaContextMenu * context_menu) 145 | { 146 | DEBUG_FUNCTION ("on_popup_hide"); 147 | DEBUG_ASSERT (widget != NULL); 148 | DEBUG_ASSERT (context_menu != NULL); 149 | DEBUG_ASSERT (context_menu->tw != NULL); 150 | 151 | tilda_window * tw = context_menu->tw; 152 | 153 | tw->disable_auto_hide = FALSE; 154 | } 155 | 156 | static void 157 | on_selection_done (GtkWidget *widget, TildaContextMenu * context_menu) 158 | { 159 | DEBUG_FUNCTION ("on_selection_done"); 160 | 161 | gtk_menu_detach (GTK_MENU (widget)); 162 | 163 | tilda_context_menu_free (context_menu); 164 | } 165 | 166 | static GMenuModel * 167 | create_menu_model (TildaContextMenu * context_menu) 168 | { 169 | GMenu * menu = g_menu_new(); 170 | 171 | // tab section 172 | 173 | GMenu *tab_section = g_menu_new (); 174 | g_menu_append (tab_section, _("_New Tab"), "window.new-tab"); 175 | g_menu_append (tab_section, _("_Close Tab"), "window.close-tab"); 176 | g_menu_append_section (menu, NULL, G_MENU_MODEL (tab_section)); 177 | 178 | // copy section 179 | 180 | GMenu *match_section = g_menu_new (); 181 | g_menu_append (match_section, _("_Copy"), "window.copy"); 182 | g_menu_append (match_section, _("_Paste"), "window.paste"); 183 | 184 | if (context_menu->match_entry != NULL) 185 | { 186 | char * copy_label; 187 | char * open_label; 188 | 189 | copy_label = tilda_match_registry_entry_get_copy_label ( 190 | context_menu->match_entry); 191 | g_menu_append (match_section, copy_label, "window.copy-match"); 192 | 193 | open_label = tilda_match_registry_entry_get_action_label ( 194 | context_menu->match_entry); 195 | 196 | if (open_label != NULL) { 197 | g_menu_append (match_section, open_label, "window.open-match"); 198 | } 199 | 200 | g_free (open_label); 201 | g_free (copy_label); 202 | } 203 | 204 | g_menu_append_section (menu, NULL, G_MENU_MODEL (match_section)); 205 | 206 | // toggle section 207 | 208 | GMenu *toggle_section = g_menu_new (); 209 | g_menu_append (toggle_section, _("_Toggle Fullscreen"), "window.fullscreen"); 210 | g_menu_append (toggle_section, _("_Toggle Searchbar"), "window.searchbar"); 211 | g_menu_append_section (menu, NULL, G_MENU_MODEL (toggle_section)); 212 | 213 | // preferences section 214 | 215 | GMenu *preferences_section = g_menu_new (); 216 | g_menu_append (preferences_section, _("_Preferences"), "window.preferences"); 217 | g_menu_append_section (menu, NULL, G_MENU_MODEL (preferences_section)); 218 | 219 | // quit section 220 | 221 | GMenu *quit_section = g_menu_new (); 222 | g_menu_append (quit_section, _("_Quit"), "window.quit"); 223 | g_menu_append_section (menu, NULL, G_MENU_MODEL (quit_section)); 224 | 225 | return G_MENU_MODEL (menu); 226 | } 227 | 228 | GtkWidget * 229 | tilda_context_menu_popup (tilda_window *tw, tilda_term *tt, const char * match, TildaMatchRegistryEntry * entry) 230 | { 231 | DEBUG_FUNCTION ("tilda_context_menu_popup"); 232 | DEBUG_ASSERT (tw != NULL); 233 | DEBUG_ASSERT (tt != NULL); 234 | 235 | TildaContextMenu * context_menu = g_new0 (TildaContextMenu, 1); 236 | context_menu->tw = tw; 237 | context_menu->tt = tt; 238 | context_menu->match = g_strdup (match); 239 | context_menu->match_entry = entry; 240 | 241 | GtkBuilder *builder = gtk_builder_new (); 242 | 243 | gtk_builder_add_from_resource (builder, "/org/tilda/menu.ui", NULL); 244 | 245 | /* Create the action group */ 246 | GSimpleActionGroup *action_group = g_simple_action_group_new (); 247 | 248 | /* We need different lists of entries because the 249 | * actions have different scope, some concern the 250 | * tilda_window and others concern the current terminal, so 251 | * when we add them to the action_group we need to pass different 252 | * user_data (tw or tt). 253 | * 254 | * Note: Using designated initializers here, allows us to skip the remaining fields which are NULL anyway and 255 | * also gets rid of missing field initializer warnings. 256 | */ 257 | GActionEntry entries_for_tilda_window[] = { 258 | { .name="new-tab", menu_add_tab_cb }, 259 | { .name="close-tab", menu_close_tab_cb }, 260 | { .name="fullscreen", menu_fullscreen_cb }, 261 | { .name="searchbar", menu_searchbar_cb }, 262 | { .name="preferences", menu_preferences_cb }, 263 | { .name="quit", menu_quit_cb } 264 | }; 265 | 266 | GActionEntry entries_for_tilda_terminal[] = { 267 | { .name="copy", menu_copy_cb}, 268 | { .name="paste", menu_paste_cb} 269 | }; 270 | 271 | GActionEntry entries_for_match_copy [] = { 272 | {.name="copy-match", menu_copy_match_cb} 273 | }; 274 | 275 | GActionEntry entries_for_match_open [] = { 276 | {.name="open-match", menu_open_match_cb} 277 | }; 278 | 279 | g_action_map_add_action_entries (G_ACTION_MAP (action_group), 280 | entries_for_tilda_window, G_N_ELEMENTS (entries_for_tilda_window), tw); 281 | g_action_map_add_action_entries (G_ACTION_MAP (action_group), 282 | entries_for_tilda_terminal, G_N_ELEMENTS (entries_for_tilda_terminal), tt); 283 | 284 | g_action_map_add_action_entries (G_ACTION_MAP (action_group), 285 | entries_for_match_copy, G_N_ELEMENTS (entries_for_match_copy), context_menu->match); 286 | 287 | g_action_map_add_action_entries (G_ACTION_MAP (action_group), 288 | entries_for_match_open, G_N_ELEMENTS (entries_for_match_open), context_menu); 289 | 290 | gtk_widget_insert_action_group (tw->window, "window", G_ACTION_GROUP (action_group)); 291 | 292 | GMenuModel *menu_model = create_menu_model (context_menu); 293 | GtkWidget *menu = gtk_menu_new_from_model (menu_model); 294 | 295 | gtk_menu_attach_to_widget (GTK_MENU (menu), tw->window, NULL); 296 | 297 | gtk_menu_set_accel_group (GTK_MENU (menu), tw->accel_group); 298 | gtk_menu_set_accel_path (GTK_MENU (menu), "/context"); 299 | 300 | /* Disable auto hide */ 301 | tw->disable_auto_hide = TRUE; 302 | g_signal_connect (G_OBJECT (menu), "unmap", G_CALLBACK (on_popup_hide), context_menu); 303 | g_signal_connect (G_OBJECT (menu), "selection-done", G_CALLBACK (on_selection_done), context_menu); 304 | 305 | g_object_unref (action_group); 306 | g_object_unref (builder); 307 | 308 | return menu; 309 | } 310 | 311 | static void 312 | tilda_context_menu_free (TildaContextMenu * context_menu) 313 | { 314 | g_free (context_menu->match); 315 | g_free (context_menu); 316 | } 317 | -------------------------------------------------------------------------------- /src/tilda-context-menu.h: -------------------------------------------------------------------------------- 1 | #ifndef TILDA_CONTEXT_MENU_H 2 | #define TILDA_CONTEXT_MENU_H 3 | 4 | #include 5 | 6 | #include "tilda_terminal.h" 7 | #include "tilda_window.h" 8 | 9 | GtkWidget * 10 | tilda_context_menu_popup (tilda_window *tw, tilda_term *tt, const char *match, TildaMatchRegistryEntry * entry); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /src/tilda-dbus-actions.c: -------------------------------------------------------------------------------- 1 | #include "tilda-dbus-actions.h" 2 | 3 | #include "key_grabber.h" 4 | #include "tilda-dbus.h" 5 | 6 | #define TILDA_DBUS_ACTIONS_BUS_NAME "com.github.lanoxx.tilda.Actions" 7 | #define TILDA_DBUS_ACTIONS_OBJECT_PATH "/com/github/lanoxx/tilda/Actions" 8 | 9 | static gchar * 10 | tilda_dbus_actions_get_bus_name_for_instance (int instance_id); 11 | 12 | static gchar * 13 | tilda_dbus_actions_get_object_path (tilda_window *window); 14 | 15 | static gchar * 16 | tilda_dbus_actions_get_object_path_for_instance (int instance_id); 17 | 18 | static gboolean 19 | on_handle_toggle (TildaDbusActions *skeleton, 20 | GDBusMethodInvocation *invocation, 21 | gpointer user_data) 22 | { 23 | tilda_window *window; 24 | 25 | window = user_data; 26 | 27 | pull (window, PULL_TOGGLE, FALSE); 28 | 29 | tilda_dbus_actions_complete_toggle (skeleton, invocation); 30 | 31 | return GDK_EVENT_STOP; 32 | } 33 | 34 | static void 35 | on_name_acquired (GDBusConnection *connection, 36 | const gchar *name, 37 | gpointer window) 38 | { 39 | TildaDbusActions *actions; 40 | tilda_window *tw; 41 | GError *error; 42 | gchar *path; 43 | 44 | tw = window; 45 | 46 | g_debug ("TildaDbusActions: Name acquired: %s", name); 47 | 48 | error = NULL; 49 | 50 | actions = tilda_dbus_actions_skeleton_new (); 51 | 52 | g_signal_connect (actions, "handle-toggle",G_CALLBACK (on_handle_toggle), window); 53 | 54 | path = tilda_dbus_actions_get_object_path (tw); 55 | 56 | g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (actions), 57 | connection, 58 | path, 59 | &error); 60 | 61 | if (error) 62 | { 63 | g_error ("Error while exporting object path of DBus interface %s: %s", 64 | TILDA_DBUS_ACTIONS_OBJECT_PATH, error->message); 65 | } 66 | 67 | g_free (path); 68 | } 69 | 70 | guint 71 | tilda_dbus_actions_init (tilda_window *window) 72 | { 73 | guint bus_identifier; 74 | gchar *name; 75 | 76 | name = tilda_dbus_actions_get_bus_name (window); 77 | 78 | bus_identifier = g_bus_own_name (G_BUS_TYPE_SESSION, 79 | name, 80 | G_BUS_NAME_OWNER_FLAGS_NONE, 81 | NULL, 82 | on_name_acquired, 83 | NULL, window, NULL); 84 | 85 | g_free (name); 86 | 87 | return bus_identifier; 88 | } 89 | 90 | void tilda_dbus_actions_toggle (gint instance_id) 91 | { 92 | GDBusConnection *conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); 93 | 94 | GError * error = NULL; 95 | 96 | if (!conn) 97 | { 98 | return; 99 | } 100 | 101 | gchar * name = tilda_dbus_actions_get_bus_name_for_instance (instance_id); 102 | gchar * path = tilda_dbus_actions_get_object_path_for_instance (instance_id); 103 | 104 | GVariant * result; 105 | 106 | result = g_dbus_connection_call_sync (conn, name, path, 107 | "com.github.lanoxx.tilda.Actions", "Toggle", 108 | NULL, NULL, G_DBUS_CALL_FLAGS_NONE, 109 | -1, NULL, &error); 110 | 111 | if (error != NULL) 112 | { 113 | g_printerr ("Failed to toggle visibility for instance %d: %s\n", 114 | instance_id, error->message); 115 | g_error_free (error); 116 | } else { 117 | g_variant_unref (result); 118 | } 119 | 120 | g_free (name); 121 | g_free (path); 122 | 123 | g_object_unref (conn); 124 | } 125 | 126 | gchar * 127 | tilda_dbus_actions_get_bus_name (tilda_window *window) 128 | { 129 | return tilda_dbus_actions_get_bus_name_for_instance (window->instance); 130 | } 131 | 132 | void 133 | tilda_dbus_actions_finish (guint bus_identifier) 134 | { 135 | g_bus_unown_name (bus_identifier); 136 | } 137 | 138 | static gchar * 139 | tilda_dbus_actions_get_bus_name_for_instance (int instance_id) { 140 | return g_strdup_printf ("%s%d", TILDA_DBUS_ACTIONS_BUS_NAME, instance_id); 141 | } 142 | 143 | static gchar * 144 | tilda_dbus_actions_get_object_path (tilda_window *window) 145 | { 146 | return tilda_dbus_actions_get_object_path_for_instance (window->instance); 147 | } 148 | 149 | static gchar * 150 | tilda_dbus_actions_get_object_path_for_instance (int instance_id) 151 | { 152 | return g_strdup_printf ("%s%d", TILDA_DBUS_ACTIONS_OBJECT_PATH, instance_id); 153 | } 154 | -------------------------------------------------------------------------------- /src/tilda-dbus-actions.h: -------------------------------------------------------------------------------- 1 | #ifndef TILDA_DBUS_ACTIONS_H 2 | #define TILDA_DBUS_ACTIONS_H 3 | 4 | #include "tilda_window.h" 5 | 6 | guint tilda_dbus_actions_init (tilda_window *window); 7 | 8 | void tilda_dbus_actions_toggle(gint instance_id); 9 | 10 | gchar *tilda_dbus_actions_get_bus_name (tilda_window *window); 11 | 12 | void tilda_dbus_actions_finish (guint bus_identifier); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/tilda-dbus-actions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/tilda-enum-types.c.template: -------------------------------------------------------------------------------- 1 | /*** BEGIN file-header ***/ 2 | #include "tilda-enum-types.h" 3 | 4 | /*** END file-header ***/ 5 | 6 | /*** BEGIN file-production ***/ 7 | /* enumerations from "@filename@" */ 8 | #include "@filename@" 9 | 10 | /*** END file-production ***/ 11 | 12 | /*** BEGIN value-header ***/ 13 | GType 14 | @enum_name@_get_type (void) 15 | { 16 | static GType the_type = 0; 17 | 18 | if (the_type == 0) 19 | { 20 | static const G@Type@Value values[] = { 21 | /*** END value-header ***/ 22 | 23 | /*** BEGIN value-production ***/ 24 | { @VALUENAME@, 25 | "@VALUENAME@", 26 | "@valuenick@" }, 27 | /*** END value-production ***/ 28 | 29 | /*** BEGIN value-tail ***/ 30 | { 0, NULL, NULL } 31 | }; 32 | the_type = g_@type@_register_static ( 33 | g_intern_static_string ("@EnumName@"), 34 | values); 35 | } 36 | return the_type; 37 | } 38 | 39 | /*** END value-tail ***/ 40 | 41 | -------------------------------------------------------------------------------- /src/tilda-enum-types.h.template: -------------------------------------------------------------------------------- 1 | /*** BEGIN file-header ***/ 2 | #ifndef TILDA_ENUM_TYPES_H 3 | #define TILDA_ENUM_TYPES_H 4 | 5 | #include 6 | 7 | G_BEGIN_DECLS 8 | 9 | /*** END file-header ***/ 10 | 11 | /*** BEGIN file-production ***/ 12 | /* Enumerations from "@filename@" */ 13 | 14 | /*** END file-production ***/ 15 | 16 | /*** BEGIN enumeration-production ***/ 17 | #define TILDA_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) 18 | GType @enum_name@_get_type (void) G_GNUC_CONST; 19 | 20 | /*** END enumeration-production ***/ 21 | 22 | /*** BEGIN file-tail ***/ 23 | G_END_DECLS 24 | 25 | #endif 26 | /*** END file-tail ***/ 27 | 28 | -------------------------------------------------------------------------------- /src/tilda-keybinding.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free software; you can redistribute it and/or modify it under 3 | * the terms of the GNU Library General Public License as published by 4 | * the Free Software Foundation; either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, but 8 | * WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Library General Public 13 | * License along with this library. If not, see . 14 | */ 15 | 16 | #ifndef TILDA_KEYBINDING_H 17 | #define TILDA_KEYBINDING_H 18 | 19 | #include 20 | 21 | #include "tilda_window.h" 22 | 23 | typedef struct TildaKeybindingTreeView_ TildaKeybindingTreeView; 24 | 25 | TildaKeybindingTreeView * 26 | tilda_keybinding_init (GtkBuilder *builder, 27 | gboolean allow_empty_pull_shortcut); 28 | 29 | void 30 | tilda_keybinding_apply (TildaKeybindingTreeView *keybinding); 31 | 32 | gboolean 33 | tilda_keybinding_save (TildaKeybindingTreeView *keybinding, 34 | tilda_window *tw); 35 | 36 | void 37 | tilda_keybinding_show_invalid_keybinding_dialog (GtkWindow *parent, 38 | const gchar* message); 39 | 40 | void 41 | tilda_keybinding_free (TildaKeybindingTreeView *keybinding); 42 | 43 | #endif //TILDA_KEYBINDING_H 44 | -------------------------------------------------------------------------------- /src/tilda-lock-files.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free software; you can redistribute it and/or modify it under 3 | * the terms of the GNU Library General Public License as published by 4 | * the Free Software Foundation; either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, but 8 | * WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Library General Public 13 | * License along with this library. If not, see . 14 | */ 15 | 16 | #include "tilda-lock-files.h" 17 | 18 | #include "debug.h" 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | static gchar *create_lock_file (struct lock_info *lock); 29 | static struct lock_info *islockfile (const gchar *filename); 30 | static GSList *getPids(); 31 | static gint remove_stale_lock_files (void); 32 | static gint get_instance_number (void); 33 | 34 | gboolean 35 | tilda_lock_files_obtain_instance_lock (struct lock_info * lock_info) 36 | { 37 | /* Remove stale lock files */ 38 | remove_stale_lock_files (); 39 | 40 | /* The global lock file is used to synchronize the start-up of multiple simultaneously starting tilda processes. 41 | * The processes will synchronize on a lock file named lock_0_0, such that the part of determining the instance 42 | * number and creating the per process lock file (lock__) is atomic. Without this it could 43 | * happen, that a second tilda instance was trying to determine its instance number before the first instance 44 | * had finished creating its lock file, this resulted in two processes with the same instance number and could lead 45 | * to corruption of the config file. 46 | * In order to test if this works the following shell command can be used: "tilda & tilda && fg", which causes 47 | * two tilda processes to be started simultaneously. See: 48 | * 49 | * http://stackoverflow.com/questions/3004811/how-do-you-run-multiple-programs-from-a-bash-script 50 | */ 51 | struct lock_info global_lock; 52 | global_lock.instance = 0; 53 | global_lock.pid = 0; 54 | gchar *global_lock_file = NULL; 55 | 56 | global_lock_file = create_lock_file(&global_lock); 57 | 58 | if(global_lock_file == NULL) { 59 | perror("Error creating global lock file."); 60 | return FALSE; 61 | } 62 | 63 | int lockResult = flock(global_lock.file_descriptor, LOCK_EX); 64 | 65 | if (lockResult == -1) { 66 | perror("Could not acquire global tilda lock file lock."); 67 | return FALSE; 68 | } 69 | 70 | /* Start of atomic section. */ 71 | lock_info->pid = getpid (); 72 | lock_info->instance = get_instance_number (); 73 | lock_info->lock_file = create_lock_file (lock_info); 74 | /* End of atomic section */ 75 | 76 | flock(global_lock.file_descriptor, LOCK_UN); 77 | close(lock_info->file_descriptor); 78 | 79 | g_free(global_lock_file); 80 | 81 | return TRUE; 82 | } 83 | 84 | void tilda_lock_files_free (struct lock_info * lock_info) 85 | { 86 | remove (lock_info->lock_file); 87 | g_free (lock_info->lock_file); 88 | lock_info->lock_file = NULL; 89 | } 90 | 91 | /** 92 | * If lock->pid is 0 then the file is not opened exclusively. Instead flock() must be used to obtain a lock. 93 | * Otherwise an exclusive lock file is created for the process. 94 | */ 95 | static gchar *create_lock_file (struct lock_info *lock) 96 | { 97 | DEBUG_FUNCTION ("create_lock_file"); 98 | DEBUG_ASSERT (lock != NULL); 99 | DEBUG_ASSERT (lock->instance >= 0); 100 | DEBUG_ASSERT (lock->pid >= 0); 101 | 102 | gint ret; 103 | gchar *lock_file_full; 104 | gchar *lock_dir = g_build_filename (g_get_user_cache_dir (), "tilda", "locks", NULL); 105 | gchar *lock_file = g_strdup_printf ("lock_%d_%d", lock->pid, lock->instance); 106 | 107 | /* Make the ~/.cache/tilda/locks directory */ 108 | ret = g_mkdir_with_parents (lock_dir, S_IRUSR | S_IWUSR | S_IXUSR); 109 | 110 | if (ret == -1) 111 | goto mkdir_fail; 112 | 113 | /* Create the full path to the lock file */ 114 | lock_file_full = g_build_filename (lock_dir, lock_file, NULL); 115 | 116 | /* Create the lock file */ 117 | if(lock->pid == 0) { 118 | ret = open(lock_file_full, O_CREAT, S_IRUSR | S_IWUSR); 119 | } else { 120 | ret = open(lock_file_full, O_WRONLY | O_CREAT | O_EXCL, 0); 121 | } 122 | 123 | if (ret == -1) 124 | goto creat_fail; 125 | 126 | lock->file_descriptor = ret; 127 | 128 | DEBUG_FUNCTION_MESSAGE("create_lock_file", "created lock file at '%s'.", lock_file_full); 129 | 130 | g_free (lock_file); 131 | g_free (lock_dir); 132 | 133 | return lock_file_full; 134 | 135 | /* Free memory and return NULL */ 136 | creat_fail: 137 | g_free (lock_file_full); 138 | mkdir_fail: 139 | g_free (lock_file); 140 | g_free (lock_dir); 141 | 142 | return NULL; 143 | } 144 | 145 | /** 146 | * Check if a filename corresponds to a valid lockfile created by tilda. Note, 147 | * that this function does NOT check whether it is a stale lock file. This 148 | * function will return a lock_info that corresponds to the lock file, if the 149 | * file uses a valid tilda lock file name. The caller needs to check if the 150 | * lock_info points to a stale lock file or if its a currently valid lock file 151 | * that belongs to an active tilda process. 152 | * 153 | * @param filename the filename to check, should point to a file with the format 154 | * lock_<pid>_<instance> in the tilda lock directory 155 | * (i.e., ${XDG_CACHE_DIR}/tilda/locks). 156 | * @return a new struct lock_info, which must be freed by the caller. 157 | * 158 | * Success: struct lock_info will be returned, with the pid and instance members 159 | * set to match the the fields encoded in filename. The file_descriptor and 160 | * lock_file members will not be set. 161 | * Failure: returns NULL 162 | */ 163 | static struct lock_info *islockfile (const gchar *filename) 164 | { 165 | DEBUG_FUNCTION ("islockfile"); 166 | DEBUG_ASSERT (filename != NULL); 167 | 168 | struct lock_info *lock; 169 | 170 | lock = g_malloc0 (sizeof (struct lock_info)); 171 | 172 | if (lock == NULL) 173 | return NULL; 174 | 175 | gboolean matches = g_str_has_prefix (filename, "lock_"); 176 | gboolean islock = FALSE; 177 | gchar *pid_s, *instance_s; 178 | 179 | if (matches) /* we are prefixed with "lock_" and are probably a lock */ 180 | { 181 | pid_s = strstr (filename, "_"); 182 | 183 | if (pid_s) /* we have a valid pid */ 184 | { 185 | /* Advance the pointer past the underscore */ 186 | pid_s++; 187 | 188 | lock->pid = atoi (pid_s); 189 | instance_s = strstr (pid_s, "_"); 190 | 191 | if (lock->pid > 0 && instance_s) 192 | { 193 | /* Advance the pointer past the underscore */ 194 | instance_s++; 195 | 196 | /* Extract the instance number and store it */ 197 | lock->instance = atoi (instance_s); 198 | 199 | /* we parsed everything, so yes, we were a lock */ 200 | islock = TRUE; 201 | } 202 | } 203 | } 204 | 205 | if (!islock) 206 | { 207 | g_free (lock); 208 | lock = NULL; 209 | } 210 | 211 | return lock; 212 | } 213 | 214 | /** 215 | * Gets a list of the pids in 216 | */ 217 | static GSList *getPids() { 218 | GSList *pids = NULL; 219 | FILE *ps_output; 220 | const gchar ps_command[] = "ps -C tilda -o pid="; 221 | gchar buf[16]; /* Really shouldn't need more than 6 */ 222 | 223 | if ((ps_output = popen (ps_command, "r")) == NULL) { 224 | g_printerr (_("Unable to run command: `%s'\n"), ps_command); 225 | return NULL; 226 | } 227 | 228 | /* The popen() succeeded, get all of the pids */ 229 | while (fgets (buf, sizeof(buf), ps_output) != NULL) 230 | pids = g_slist_append (pids, GINT_TO_POINTER (atoi (buf))); 231 | 232 | /* We've read all of the pids, exit */ 233 | pclose (ps_output); 234 | return pids; 235 | } 236 | 237 | /** 238 | * Remove stale lock files from the ~/.tilda/locks/ directory. 239 | * 240 | * Success: returns 0 241 | * Failure: returns non-zero 242 | */ 243 | static gint remove_stale_lock_files (void) 244 | { 245 | DEBUG_FUNCTION ("remove_stale_lock_files"); 246 | 247 | GSList *pids = getPids(); 248 | if(pids == NULL) { 249 | return -1; 250 | } 251 | 252 | struct lock_info *lock; 253 | gchar *lock_dir = g_build_filename (g_get_user_cache_dir (), "tilda", "locks", NULL); 254 | gchar *remove_file; 255 | gchar *filename; 256 | GDir *dir; 257 | 258 | /* if the lock dir does not exist then there are no stale lock files to remove. */ 259 | if (!g_file_test (lock_dir, G_FILE_TEST_EXISTS)) { 260 | g_free (lock_dir); 261 | return 0; 262 | } 263 | 264 | /* Open the lock directory for reading */ 265 | dir = g_dir_open (lock_dir, 0, NULL); 266 | 267 | if (dir == NULL) 268 | { 269 | g_printerr (_("Unable to open lock directory: %s\n"), lock_dir); 270 | g_free (lock_dir); 271 | return -2; 272 | } 273 | 274 | /* For each possible lock file, check if it is a lock, and see if 275 | * it matches one of the running tildas */ 276 | while ((filename = (gchar*) g_dir_read_name (dir)) != NULL) 277 | { 278 | lock = islockfile (filename); 279 | 280 | if (lock && (g_slist_find (pids, GINT_TO_POINTER (lock->pid)) == NULL)) 281 | { 282 | /* We have found a stale element */ 283 | remove_file = g_build_filename (lock_dir, filename, NULL); 284 | remove (remove_file); 285 | g_free (remove_file); 286 | } 287 | 288 | if (lock) 289 | g_free (lock); 290 | } 291 | 292 | g_dir_close (dir); 293 | g_free (lock_dir); 294 | g_slist_free(pids); 295 | 296 | return 0; 297 | } 298 | 299 | static gint _cmp_locks(gconstpointer a, gconstpointer b, gpointer userdata) { 300 | return GPOINTER_TO_INT (a) - GPOINTER_TO_INT (b); 301 | } 302 | 303 | /** 304 | * get_instance_number () 305 | * 306 | * Gets the next available tilda instance number. This will always pick the 307 | * lowest non-running tilda available. 308 | * 309 | * Success: return next available instance number (>=0) 310 | * Failure: return 0 311 | */ 312 | static gint get_instance_number () 313 | { 314 | DEBUG_FUNCTION ("get_instance_number"); 315 | 316 | gchar *name; 317 | 318 | GSequence *seq; 319 | GSequenceIter *iter; 320 | gint lowest_lock_instance = 0; 321 | gint current_lock_instance; 322 | 323 | GDir *dir; 324 | struct lock_info *lock; 325 | gchar *lock_dir = g_build_filename (g_get_user_cache_dir (), "tilda", "locks", NULL); 326 | 327 | /* Open the lock directory */ 328 | dir = g_dir_open (lock_dir, 0, NULL); 329 | 330 | /* Check for failure to open */ 331 | if (dir == NULL) 332 | { 333 | g_printerr (_("Unable to open lock directory: %s\n"), lock_dir); 334 | g_free (lock_dir); 335 | return 0; 336 | } 337 | 338 | /* Look through every file in the lock directory, and see if it is a lock file. 339 | * If it is a lock file, insert it in a sorted sequence. */ 340 | seq = g_sequence_new(NULL); 341 | while ((name = (gchar*)g_dir_read_name (dir)) != NULL) 342 | { 343 | lock = islockfile (name); 344 | 345 | if (lock != NULL) 346 | { 347 | g_sequence_insert_sorted(seq, GINT_TO_POINTER(lock->instance), _cmp_locks, NULL); 348 | g_free (lock); 349 | } 350 | } 351 | 352 | g_dir_close (dir); 353 | g_free (lock_dir); 354 | 355 | /* We iterate the sorted sequence of lock instances to find the first (lowest) number *not* taken. */ 356 | for (iter = g_sequence_get_begin_iter(seq); !g_sequence_iter_is_end(iter); iter = g_sequence_iter_next(iter)) { 357 | current_lock_instance = GPOINTER_TO_INT(g_sequence_get(iter)); 358 | if (lowest_lock_instance < current_lock_instance) 359 | break; 360 | else 361 | lowest_lock_instance = current_lock_instance + 1; 362 | } 363 | 364 | g_sequence_free(seq); 365 | 366 | DEBUG_FUNCTION_MESSAGE("get_instance_number", "assigned instance: %d", lowest_lock_instance); 367 | 368 | return lowest_lock_instance; 369 | } 370 | -------------------------------------------------------------------------------- /src/tilda-lock-files.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free software; you can redistribute it and/or modify it under 3 | * the terms of the GNU Library General Public License as published by 4 | * the Free Software Foundation; either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, but 8 | * WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Library General Public 13 | * License along with this library. If not, see . 14 | */ 15 | 16 | #ifndef TILDA_LOCK_FILES_H 17 | #define TILDA_LOCK_FILES_H 18 | 19 | #include "glib.h" 20 | 21 | struct lock_info 22 | { 23 | gint pid; 24 | gint instance; 25 | gint file_descriptor; 26 | char * lock_file; 27 | }; 28 | 29 | gboolean tilda_lock_files_obtain_instance_lock (struct lock_info * lock_info); 30 | 31 | void tilda_lock_files_free (struct lock_info * lock_info); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/tilda-match-registry.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free software; you can redistribute it and/or modify it under 3 | * the terms of the GNU Library General Public License as published by 4 | * the Free Software Foundation; either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, but 8 | * WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Library General Public 13 | * License along with this library. If not, see . 14 | */ 15 | 16 | #include "tilda-match-registry.h" 17 | #include "tilda-regex.h" 18 | #include 19 | 20 | /** 21 | * The TildaMatchRegistry acts as a central class for all types of matches that 22 | * the terminal can detect. When the TildaMatchRegistry is used, users can 23 | * choose to activate all patterns or only selected patterns. 24 | * 25 | * For each pattern, the registry handles conversion of a match to a proper URI 26 | * (if the matched pattern supports this), and it can return action labels to 27 | * copy and open the match. If a match is not an URI (such as a number match) 28 | * then it can only be copied but not opened. 29 | */ 30 | 31 | #define PCRE2_CODE_UNIT_WIDTH 0 32 | #include 33 | 34 | typedef char * (* MatchToUriFunc) (const char * match); 35 | 36 | typedef struct { 37 | const char *pattern; 38 | TildaMatchRegistryFlavor flavor; 39 | const char *copy_action_label; 40 | const char *open_action_label; 41 | MatchToUriFunc match_to_uri; 42 | gboolean is_uri; 43 | } PatternItem; 44 | 45 | static char * default_match_to_uri (const char * match); 46 | static char * http_match_to_uri (const char * match); 47 | static char * email_match_to_uri (const char * match); 48 | 49 | static const PatternItem hyperlink_pattern = { 50 | NULL, TILDA_MATCH_FLAVOR_URL, "_Copy Link", "_Open Link", default_match_to_uri, TRUE 51 | }; 52 | 53 | static const PatternItem pattern_items[] = { 54 | { REGEX_URL_AS_IS, TILDA_MATCH_FLAVOR_URL, N_("Copy Link"), N_("Open Link"), default_match_to_uri, TRUE }, 55 | { REGEX_URL_HTTP, TILDA_MATCH_FLAVOR_DEFAULT_TO_HTTP, N_("Copy Link"), N_("Open Link"), http_match_to_uri, TRUE }, 56 | { REGEX_URL_FILE, TILDA_MATCH_FLAVOR_FILE, N_("Copy File"), N_("Open File"), default_match_to_uri, TRUE }, 57 | { REGEX_EMAIL, TILDA_MATCH_FLAVOR_EMAIL, N_("Copy Email"), N_("Send Email"), email_match_to_uri, TRUE }, 58 | { REGEX_NUMBER, TILDA_MATCH_FLAVOR_NUMBER, N_("Copy Number"), NULL, NULL, FALSE } 59 | }; 60 | 61 | struct TildaMatchRegistry_ { 62 | GHashTable *entries; 63 | TildaMatchRegistryEntry * hyperlink_entry; 64 | }; 65 | 66 | struct TildaMatchRegistryEntry_ { 67 | const PatternItem * pattern; 68 | VteRegex * regex; 69 | }; 70 | 71 | static void 72 | tilda_match_registry_add (TildaMatchRegistry * registry, 73 | const PatternItem *pattern_item, 74 | VteRegex * regex, 75 | int tag); 76 | 77 | static void registry_entry_free (gpointer data) 78 | { 79 | TildaMatchRegistryEntry * entry = data; 80 | 81 | if (entry->regex != NULL) { 82 | vte_regex_unref (entry->regex); 83 | } 84 | 85 | g_slice_free (TildaMatchRegistryEntry, data); 86 | } 87 | 88 | TildaMatchRegistry * 89 | tilda_match_registry_new () 90 | { 91 | TildaMatchRegistry * registry = g_new0 (TildaMatchRegistry, 1); 92 | 93 | registry->entries = g_hash_table_new_full(NULL, 94 | NULL, 95 | NULL, 96 | registry_entry_free); 97 | 98 | TildaMatchRegistryEntry * entry = g_slice_new0 (TildaMatchRegistryEntry); 99 | 100 | entry->pattern = &hyperlink_pattern; 101 | 102 | registry->hyperlink_entry = entry; 103 | 104 | return registry; 105 | } 106 | 107 | static void 108 | tilda_match_registry_add (TildaMatchRegistry * registry, 109 | const PatternItem *pattern_item, 110 | VteRegex * regex, 111 | int tag) 112 | { 113 | TildaMatchRegistryEntry * entry = g_slice_new0 (TildaMatchRegistryEntry); 114 | 115 | entry->pattern = pattern_item; 116 | entry->regex = regex; 117 | 118 | g_hash_table_insert (registry->entries, GINT_TO_POINTER (tag), entry); 119 | } 120 | 121 | /** 122 | * tilda_match_registry_for_each: 123 | * @registry: An instance of a TildaMatchRegistry. 124 | * @callback: A function to call for each item in the registry. 125 | * @user_data: user data to pass to the function. 126 | */ 127 | /** 128 | * TildaMatchHookFunc: 129 | * @regex: The VteRegex begin enumerated. 130 | * @user_data: The user data passed to tilda_match_registry_for_each() 131 | * 132 | * Declares a type of function that can be passed to 133 | * tilda_match_registry_for_each() to perform an action on each item 134 | * in the registry. 135 | * 136 | * Returns: A tag to be stored with the regex or TILDA_MATCH_REGISTRY_IGNORE 137 | * if the regex should not be registered. 138 | */ 139 | void tilda_match_registry_for_each (TildaMatchRegistry * registry, 140 | TildaMatchHookFunc callback, 141 | gpointer user_data) 142 | { 143 | guint32 flags = PCRE2_CASELESS | PCRE2_MULTILINE; 144 | 145 | for (guint i = 0; i < G_N_ELEMENTS (pattern_items); i++) 146 | { 147 | GError * error = NULL; 148 | const PatternItem * pattern_item = pattern_items + i; 149 | 150 | VteRegex * regex = vte_regex_new_for_match (pattern_item->pattern, 151 | -1, 152 | flags, 153 | &error); 154 | 155 | if (error) { 156 | g_critical ("Could not register match pattern for flavor %d: %s", 157 | pattern_item->flavor, 158 | error->message); 159 | g_error_free (error); 160 | } 161 | 162 | gint tag = callback (regex, pattern_item->flavor, user_data); 163 | 164 | if (tag == TILDA_MATCH_REGISTRY_IGNORE) { 165 | continue; 166 | } 167 | 168 | tilda_match_registry_add (registry, pattern_item, regex, tag); 169 | } 170 | } 171 | 172 | TildaMatchRegistryEntry * 173 | tilda_match_registry_lookup_by_tag (TildaMatchRegistry * registry, 174 | gint tag) 175 | { 176 | TildaMatchRegistryEntry * entry; 177 | 178 | if (tag < 0) { 179 | return NULL; 180 | } 181 | 182 | entry = g_hash_table_lookup(registry->entries, GINT_TO_POINTER(tag)); 183 | 184 | return entry; 185 | } 186 | 187 | TildaMatchRegistryEntry * 188 | tilda_match_registry_get_hyperlink_entry (TildaMatchRegistry * registry) 189 | { 190 | return registry->hyperlink_entry; 191 | } 192 | 193 | char * 194 | tilda_match_registry_entry_get_action_label (TildaMatchRegistryEntry * entry) 195 | { 196 | g_return_val_if_fail(entry != NULL, NULL); 197 | g_return_val_if_fail(entry->pattern != NULL, NULL); 198 | 199 | const char * open_action_label = entry->pattern->open_action_label; 200 | 201 | if (open_action_label == NULL) { 202 | return NULL; 203 | } 204 | 205 | return g_strdup (entry->pattern->open_action_label); 206 | } 207 | 208 | char * 209 | tilda_match_registry_entry_get_copy_label (TildaMatchRegistryEntry * entry) 210 | { 211 | g_return_val_if_fail(entry != NULL, NULL); 212 | g_return_val_if_fail(entry->pattern != NULL, NULL); 213 | 214 | return g_strdup(entry->pattern->copy_action_label); 215 | } 216 | 217 | TildaMatchRegistryFlavor 218 | tilda_match_registry_entry_get_flavor (TildaMatchRegistryEntry * entry) 219 | { 220 | g_return_val_if_fail(entry != NULL, TILDA_MATCH_FLAVOR_LAST); 221 | g_return_val_if_fail(entry->pattern != NULL, TILDA_MATCH_FLAVOR_LAST); 222 | 223 | return entry->pattern->flavor; 224 | } 225 | 226 | gboolean 227 | tilda_match_registry_flavor_is_uri (TildaMatchRegistryEntry * entry) 228 | { 229 | g_return_val_if_fail(entry != NULL, FALSE); 230 | g_return_val_if_fail(entry->pattern != NULL, FALSE); 231 | 232 | return entry->pattern->is_uri; 233 | } 234 | 235 | char * 236 | tilda_match_registry_entry_get_uri_from_match (TildaMatchRegistryEntry * entry, const char * match) 237 | { 238 | g_return_val_if_fail(entry != NULL, NULL); 239 | g_return_val_if_fail(entry->pattern != NULL, NULL); 240 | g_return_val_if_fail(match != NULL, NULL); 241 | 242 | if (entry->pattern->match_to_uri == NULL) { 243 | return NULL; 244 | } 245 | 246 | return entry->pattern->match_to_uri (match); 247 | } 248 | 249 | static char * 250 | email_match_to_uri (const char * match) 251 | { 252 | char * uri; 253 | const char * mailto_prefix = "mailto:"; 254 | 255 | if (g_ascii_strncasecmp(mailto_prefix, match, strlen(mailto_prefix) != 0)) { 256 | uri = g_strdup_printf ("%s%s", mailto_prefix, match); 257 | } else { 258 | uri = g_strdup (match); 259 | } 260 | 261 | return uri; 262 | } 263 | 264 | static char * 265 | default_match_to_uri (const char * match) 266 | { 267 | return g_strdup(match); 268 | } 269 | 270 | static char * 271 | http_match_to_uri (const char * match) 272 | { 273 | return g_strdup_printf("http://%s", match); 274 | } 275 | 276 | void tilda_match_registry_free (TildaMatchRegistry * registry) 277 | { 278 | g_hash_table_destroy(registry->entries); 279 | 280 | registry_entry_free(registry->hyperlink_entry); 281 | 282 | g_free (registry); 283 | } 284 | -------------------------------------------------------------------------------- /src/tilda-match-registry.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free software; you can redistribute it and/or modify it under 3 | * the terms of the GNU Library General Public License as published by 4 | * the Free Software Foundation; either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, but 8 | * WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Library General Public 13 | * License along with this library. If not, see . 14 | */ 15 | 16 | #ifndef TILDA_MATCH_REGISTRY_H 17 | #define TILDA_MATCH_REGISTRY_H 18 | 19 | #include 20 | #include 21 | 22 | typedef enum { 23 | TILDA_MATCH_FLAVOR_URL, 24 | TILDA_MATCH_FLAVOR_DEFAULT_TO_HTTP, 25 | TILDA_MATCH_FLAVOR_FILE, 26 | TILDA_MATCH_FLAVOR_EMAIL, 27 | TILDA_MATCH_FLAVOR_NUMBER, 28 | TILDA_MATCH_FLAVOR_LAST 29 | } TildaMatchRegistryFlavor; 30 | 31 | typedef struct TildaMatchRegistry_ TildaMatchRegistry; 32 | 33 | typedef struct TildaMatchRegistryEntry_ TildaMatchRegistryEntry; 34 | 35 | typedef int (*TildaMatchHookFunc)(VteRegex * regex, TildaMatchRegistryFlavor flavor, gpointer user_data); 36 | 37 | #define TILDA_MATCH_REGISTRY_IGNORE -1 38 | 39 | TildaMatchRegistry * 40 | tilda_match_registry_new (void); 41 | 42 | void 43 | tilda_match_registry_for_each (TildaMatchRegistry * registry, 44 | TildaMatchHookFunc callback, 45 | gpointer user_data); 46 | 47 | TildaMatchRegistryEntry * 48 | tilda_match_registry_lookup_by_tag (TildaMatchRegistry * registry, 49 | gint tag); 50 | 51 | TildaMatchRegistryEntry * 52 | tilda_match_registry_get_hyperlink_entry (TildaMatchRegistry * registry); 53 | 54 | char * 55 | tilda_match_registry_entry_get_action_label (TildaMatchRegistryEntry * entry); 56 | 57 | char * 58 | tilda_match_registry_entry_get_copy_label (TildaMatchRegistryEntry * entry); 59 | 60 | TildaMatchRegistryFlavor 61 | tilda_match_registry_entry_get_flavor (TildaMatchRegistryEntry * entry); 62 | 63 | gboolean 64 | tilda_match_registry_flavor_is_uri (TildaMatchRegistryEntry * entry); 65 | 66 | char * 67 | tilda_match_registry_entry_get_uri_from_match (TildaMatchRegistryEntry * entry, 68 | const char * match); 69 | 70 | void 71 | tilda_match_registry_free (TildaMatchRegistry * registry); 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /src/tilda-palettes.c: -------------------------------------------------------------------------------- 1 | #include "tilda.h" 2 | #include "tilda-palettes.h" 3 | 4 | #include 5 | 6 | static GdkRGBA tilda_palettes_current_palette[TILDA_COLOR_PALETTE_SIZE]; 7 | 8 | static const GdkRGBA 9 | terminal_palette_tango[TILDA_COLOR_PALETTE_SIZE] = { 10 | { RGB(0x2e2e, 0x3434, 0x3636) }, //1. black 11 | { RGB(0xcccc, 0x0000, 0x0000) }, //2. darkred 12 | { RGB(0x4e4e, 0x9a9a, 0x0606) }, //3. darkgreen 13 | { RGB(0xc4c4, 0xa0a0, 0x0000) }, //4. brown 14 | { RGB(0x3434, 0x6565, 0xa4a4) }, //5. darkblue 15 | { RGB(0x7575, 0x5050, 0x7b7b) }, //6. darkmagenta 16 | { RGB(0x0606, 0x9898, 0x9a9a) }, //7. darkcyan 17 | { RGB(0xd3d3, 0xd7d7, 0xcfcf) }, //8. lightgrey 18 | { RGB(0x5555, 0x5757, 0x5353) }, //9. darkgrey 19 | { RGB(0xefef, 0x2929, 0x2929) }, //10. red 20 | { RGB(0x8a8a, 0xe2e2, 0x3434) }, //11. green 21 | { RGB(0xfcfc, 0xe9e9, 0x4f4f) }, //12. yellow 22 | { RGB(0x7272, 0x9f9f, 0xcfcf) }, //13. blue 23 | { RGB(0xadad, 0x7f7f, 0xa8a8) }, //14. magenta 24 | { RGB(0x3434, 0xe2e2, 0xe2e2) }, //15. cyan 25 | { RGB(0xeeee, 0xeeee, 0xecec) } //16. white 26 | }; 27 | 28 | static const GdkRGBA 29 | terminal_palette_zenburn[TILDA_COLOR_PALETTE_SIZE] = { 30 | { RGB(0x2222, 0x2222, 0x2222) }, //black 31 | { RGB(0x8080, 0x3232, 0x3232) }, //darkred 32 | { RGB(0x5b5b, 0x7676, 0x2f2f) }, //darkgreen 33 | { RGB(0xaaaa, 0x9999, 0x4343) }, //brown 34 | { RGB(0x3232, 0x4c4c, 0x8080) }, //darkblue 35 | { RGB(0x7070, 0x6c6c, 0x9a9a) }, //darkmagenta 36 | { RGB(0x9292, 0xb1b1, 0x9e9e) }, //darkcyan 37 | { RGB(0xffff, 0xffff, 0xffff) }, //lightgrey 38 | { RGB(0x2222, 0x2222, 0x2222) }, //darkgrey 39 | { RGB(0x9898, 0x2b2b, 0x2b2b) }, //red 40 | { RGB(0x8989, 0xb8b8, 0x3f3f) }, //green 41 | { RGB(0xefef, 0xefef, 0x6060) }, //yellow 42 | { RGB(0x2b2b, 0x4f4f, 0x9898) }, //blue 43 | { RGB(0x8282, 0x6a6a, 0xb1b1) }, //magenta 44 | { RGB(0xa1a1, 0xcdcd, 0xcdcd) }, //cyan 45 | { RGB(0xdede, 0xdede, 0xdede) }, //white} 46 | }; 47 | 48 | static const GdkRGBA 49 | terminal_palette_linux[TILDA_COLOR_PALETTE_SIZE] = { 50 | { RGB(0x0000, 0x0000, 0x0000) }, 51 | { RGB(0xaaaa, 0x0000, 0x0000) }, 52 | { RGB(0x0000, 0xaaaa, 0x0000) }, 53 | { RGB(0xaaaa, 0x5555, 0x0000) }, 54 | { RGB(0x0000, 0x0000, 0xaaaa) }, 55 | { RGB(0xaaaa, 0x0000, 0xaaaa) }, 56 | { RGB(0x0000, 0xaaaa, 0xaaaa) }, 57 | { RGB(0xaaaa, 0xaaaa, 0xaaaa) }, 58 | { RGB(0x5555, 0x5555, 0x5555) }, 59 | { RGB(0xffff, 0x5555, 0x5555) }, 60 | { RGB(0x5555, 0xffff, 0x5555) }, 61 | { RGB(0xffff, 0xffff, 0x5555) }, 62 | { RGB(0x5555, 0x5555, 0xffff) }, 63 | { RGB(0xffff, 0x5555, 0xffff) }, 64 | { RGB(0x5555, 0xffff, 0xffff) }, 65 | { RGB(0xffff, 0xffff, 0xffff) } 66 | }; 67 | 68 | static const GdkRGBA 69 | terminal_palette_xterm[TILDA_COLOR_PALETTE_SIZE] = { 70 | {RGB(0x0000, 0x0000, 0x0000) }, 71 | {RGB(0xcdcb, 0x0000, 0x0000) }, 72 | {RGB(0x0000, 0xcdcb, 0x0000) }, 73 | {RGB(0xcdcb, 0xcdcb, 0x0000) }, 74 | {RGB(0x1e1a, 0x908f, 0xffff) }, 75 | {RGB(0xcdcb, 0x0000, 0xcdcb) }, 76 | {RGB(0x0000, 0xcdcb, 0xcdcb) }, 77 | {RGB(0xe5e2, 0xe5e2, 0xe5e2) }, 78 | {RGB(0x4ccc, 0x4ccc, 0x4ccc) }, 79 | {RGB(0xffff, 0x0000, 0x0000) }, 80 | {RGB(0x0000, 0xffff, 0x0000) }, 81 | {RGB(0xffff, 0xffff, 0x0000) }, 82 | {RGB(0x4645, 0x8281, 0xb4ae) }, 83 | {RGB(0xffff, 0x0000, 0xffff) }, 84 | {RGB(0x0000, 0xffff, 0xffff) }, 85 | {RGB(0xffff, 0xffff, 0xffff) } 86 | }; 87 | 88 | static const GdkRGBA 89 | terminal_palette_rxvt[TILDA_COLOR_PALETTE_SIZE] = { 90 | { RGB(0x0000, 0x0000, 0x0000) }, 91 | { RGB(0xcdcd, 0x0000, 0x0000) }, 92 | { RGB(0x0000, 0xcdcd, 0x0000) }, 93 | { RGB(0xcdcd, 0xcdcd, 0x0000) }, 94 | { RGB(0x0000, 0x0000, 0xcdcd) }, 95 | { RGB(0xcdcd, 0x0000, 0xcdcd) }, 96 | { RGB(0x0000, 0xcdcd, 0xcdcd) }, 97 | { RGB(0xfafa, 0xebeb, 0xd7d7) }, 98 | { RGB(0x4040, 0x4040, 0x4040) }, 99 | { RGB(0xffff, 0x0000, 0x0000) }, 100 | { RGB(0x0000, 0xffff, 0x0000) }, 101 | { RGB(0xffff, 0xffff, 0x0000) }, 102 | { RGB(0x0000, 0x0000, 0xffff) }, 103 | { RGB(0xffff, 0x0000, 0xffff) }, 104 | { RGB(0x0000, 0xffff, 0xffff) }, 105 | { RGB(0xffff, 0xffff, 0xffff) } 106 | }; 107 | 108 | static const GdkRGBA 109 | terminal_palette_solarizedL[TILDA_COLOR_PALETTE_SIZE] = { 110 | { RGB(0xeeee, 0xe8e8, 0xd5d5) }, 111 | { RGB(0xdcdc, 0x3232, 0x2f2f) }, 112 | { RGB(0x8585, 0x9999, 0x0000) }, 113 | { RGB(0xb5b5, 0x8989, 0x0000) }, 114 | { RGB(0x2626, 0x8b8b, 0xd2d2) }, 115 | { RGB(0xd3d3, 0x3636, 0x8282) }, 116 | { RGB(0x2a2a, 0xa1a1, 0x9898) }, 117 | { RGB(0x0707, 0x3636, 0x4242) }, 118 | { RGB(0xfdfd, 0xf6f6, 0xe3e3) }, 119 | { RGB(0xcbcb, 0x4b4b, 0x1616) }, 120 | { RGB(0x9393, 0xa1a1, 0xa1a1) }, 121 | { RGB(0x8383, 0x9494, 0x9696) }, 122 | { RGB(0x6565, 0x7b7b, 0x8383) }, 123 | { RGB(0x6c6c, 0x7171, 0xc4c4) }, 124 | { RGB(0x5858, 0x6e6e, 0x7575) }, 125 | { RGB(0x0000, 0x2b2b, 0x3636) } 126 | }; 127 | 128 | static const GdkRGBA 129 | terminal_palette_solarizedD[TILDA_COLOR_PALETTE_SIZE] = { 130 | { RGB(0x0707, 0x3636, 0x4242) }, 131 | { RGB(0xdcdc, 0x3232, 0x2f2f) }, 132 | { RGB(0x8585, 0x9999, 0x0000) }, 133 | { RGB(0xb5b5, 0x8989, 0x0000) }, 134 | { RGB(0x2626, 0x8b8b, 0xd2d2) }, 135 | { RGB(0xd3d3, 0x3636, 0x8282) }, 136 | { RGB(0x2a2a, 0xa1a1, 0x9898) }, 137 | { RGB(0xeeee, 0xe8e8, 0xd5d5) }, 138 | { RGB(0x0000, 0x2b2b, 0x3636) }, 139 | { RGB(0xcbcb, 0x4b4b, 0x1616) }, 140 | { RGB(0x5858, 0x6e6e, 0x7575) }, 141 | { RGB(0x8383, 0x9494, 0x9696) }, 142 | { RGB(0x6565, 0x7b7b, 0x8383) }, 143 | { RGB(0x6c6c, 0x7171, 0xc4c4) }, 144 | { RGB(0x9393, 0xa1a1, 0xa1a1) }, 145 | { RGB(0xfdfd, 0xf6f6, 0xe3e3) } 146 | }; 147 | 148 | static const GdkRGBA 149 | terminal_palette_snazzy[TILDA_COLOR_PALETTE_SIZE] = { 150 | { RGB(0x2828, 0x2a2a, 0x3636) }, 151 | { RGB(0xffff, 0x5c5c, 0x5757) }, 152 | { RGB(0x5a5a, 0xf7f7, 0x8e8e) }, 153 | { RGB(0xf3f3, 0xf9f9, 0x9d9d) }, 154 | { RGB(0x5757, 0xc7c7, 0xffff) }, 155 | { RGB(0xffff, 0x6a6a, 0xc1c1) }, 156 | { RGB(0x9a9a, 0xeded, 0xfefe) }, 157 | { RGB(0xf1f1, 0xf1f1, 0xf0f0) }, 158 | { RGB(0x6868, 0x6868, 0x6868) }, 159 | { RGB(0xffff, 0x5c5c, 0x5757) }, 160 | { RGB(0x5a5a, 0xf7f7, 0x8e8e) }, 161 | { RGB(0xf3f3, 0xf9f9, 0x9d9d) }, 162 | { RGB(0x5757, 0xc7c7, 0xffff) }, 163 | { RGB(0xffff, 0x6a6a, 0xc1c1) }, 164 | { RGB(0x9a9a, 0xeded, 0xfefe) }, 165 | { RGB(0xf1f1, 0xf1f1, 0xf0f0) } 166 | }; 167 | 168 | static TildaColorScheme palette_schemes[] = { 169 | { N_("Custom"), NULL }, 170 | { N_("Tango"), terminal_palette_tango }, 171 | { N_("Linux console"), terminal_palette_linux }, 172 | { N_("XTerm"), terminal_palette_xterm }, 173 | { N_("Rxvt"), terminal_palette_rxvt }, 174 | { N_("Zenburn"), terminal_palette_zenburn }, 175 | { N_("Solarized Light (deprecated)"), terminal_palette_solarizedL }, 176 | { N_("Solarized"), terminal_palette_solarizedD }, 177 | { N_("Snazzy"), terminal_palette_snazzy } 178 | }; 179 | 180 | gint tilda_palettes_get_n_palette_schemes () 181 | { 182 | return G_N_ELEMENTS (palette_schemes); 183 | } 184 | 185 | TildaColorScheme * tilda_palettes_get_palette_schemes () 186 | { 187 | return palette_schemes; 188 | } 189 | 190 | void tilda_palettes_set_current_palette (const GdkRGBA *palette) 191 | { 192 | memcpy (tilda_palettes_current_palette, palette, 193 | TILDA_COLOR_PALETTE_SIZE); 194 | } 195 | 196 | GdkRGBA *tilda_palettes_get_current_palette () 197 | { 198 | return tilda_palettes_current_palette; 199 | } 200 | 201 | const GdkRGBA *tilda_palettes_get_palette_color (const GdkRGBA *palette, 202 | int color_num) 203 | { 204 | g_return_val_if_fail (color_num >= 0 && color_num < TILDA_COLOR_PALETTE_SIZE, 205 | NULL); 206 | 207 | return palette + color_num; 208 | } 209 | -------------------------------------------------------------------------------- /src/tilda-palettes.h: -------------------------------------------------------------------------------- 1 | #ifndef TILDA_PALETTES_H 2 | #define TILDA_PALETTES_H 3 | 4 | #include 5 | 6 | G_BEGIN_DECLS 7 | 8 | /** 9 | * The number of colors contained in a #TildaColorPalette. 10 | */ 11 | #define TILDA_COLOR_PALETTE_SIZE 16 12 | 13 | /** 14 | * A color scheme links a color scheme name to its corresponding 15 | * color palette. 16 | */ 17 | typedef struct _TildaColorPaletteScheme 18 | { 19 | const char *name; 20 | const GdkRGBA *palette; 21 | } TildaColorScheme; 22 | 23 | /** 24 | * Gets a list of color schemes. Use 25 | * tilda_palettes_get_n_palette_schemes to 26 | * determine the number of color schemes. 27 | * 28 | * @return A pointer to an array of color schemes. 29 | */ 30 | TildaColorScheme *tilda_palettes_get_palette_schemes (void); 31 | 32 | /** 33 | * Gets the number of palette schemes. 34 | * 35 | * @return The number of color schemes contained in 36 | * #tilda_palettes_get_palette_schemes. 37 | */ 38 | gint tilda_palettes_get_n_palette_schemes (void); 39 | 40 | /** 41 | * Get the currently active color palette. 42 | * 43 | * @return A pointer to a color palette of size TILDA_COLOR_PALETTE_SIZE 44 | * with GdkRGBA colors. The color palette is owned by tilda 45 | * and must not be freed. 46 | */ 47 | GdkRGBA *tilda_palettes_get_current_palette (void); 48 | 49 | /** 50 | * Sets the currently active color palette. 51 | * 52 | * @param palette A pointer to a color palette of size TILDA_COLOR_PALETTE_SIZE. 53 | */ 54 | void tilda_palettes_set_current_palette (const GdkRGBA *palette); 55 | 56 | /** 57 | * Gets the color at the specified position from the palette. 58 | * 59 | * @param palette A TildaColorPalette of size TILDA_COLOR_PALETTE_SIZE. 60 | * @param color_num Position of the color in the palette. 61 | * @return A pointer to a GdkRGBA color struct. 62 | */ 63 | const GdkRGBA *tilda_palettes_get_palette_color (const GdkRGBA *palette, 64 | int color_num); 65 | 66 | G_END_DECLS 67 | 68 | #endif //TILDA_PALETTES_H 69 | -------------------------------------------------------------------------------- /src/tilda-regex.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Egmont Koblinger 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | /* 19 | * Mini style-guide: 20 | * 21 | * #define'd fragments should preferably have an outermost group, for the 22 | * exact same reason as why usually in C/C++ #define's the values are enclosed 23 | * in parentheses: that is, so that you don't get surprised when you use the 24 | * macro and append a quantifier. 25 | * 26 | * For repeated fragments prefer regex-style (?(DEFINE)(?(...))) and use 27 | * as (?&NAME), so that the regex string and the compiled regex object is 28 | * smaller. 29 | * 30 | * Build small blocks, comment and unittest them heavily. 31 | * 32 | * Use free-spacing mode for improved readability. The hardest to read is 33 | * which additional characters belong to a "(?" prefix. To improve 34 | * readability, place a space after this, and for symmetry, before the closing 35 | * parenthesis. Also place a space around "|" characters. No space before 36 | * quantifiers. Try to be consistent with the existing style (yes I know the 37 | * existing style is not consistent either, but please do your best). 38 | * 39 | * See http://www.rexegg.com/regex-disambiguation.html for all the "(?" 40 | * syntaxes. 41 | */ 42 | 43 | #ifndef TERMINAL_REGEX_H 44 | #define TERMINAL_REGEX_H 45 | 46 | /* Lookbehind to see if there's a preceding apostrophe. 47 | * Unlike the other *_DEF macros which define regex subroutines, 48 | * this one is a named capture that defines APOS_START to either 49 | * an apostrophe or the empty string, depending on the character 50 | * preceding this APOS_START_DEF construct. */ 51 | #define APOS_START_DEF "(?(?<='))?" 52 | 53 | #define SCHEME "(?ix: https? | ftps? | sftp )" 54 | 55 | #define USERCHARS "-+.[:alnum:]" 56 | /* Nonempty username, e.g. "john.smith" */ 57 | #define USER "[" USERCHARS "]+" 58 | 59 | #define PASSCHARS_CLASS "[-[:alnum:]\\Q,?;.:/!%$^*&~\"#'\\E]" 60 | 61 | /* Optional colon-prefixed password. I guess empty password should be allowed, right? E.g. ":secret", ":", "" */ 62 | #define PASS "(?x: :" PASSCHARS_CLASS "* )?" 63 | 64 | /* Optional at-terminated username (with perhaps a password too), e.g. "joe@", "pete:secret@", "" */ 65 | #define USERPASS "(?:" USER PASS "@)?" 66 | 67 | /* S4: IPv4 segment (number between 0 and 255) with lookahead at the end so that we don't match "25" in the string "256". 68 | The lookahead could go to the last segment of IPv4 only but this construct allows nicer unittesting. */ 69 | #define S4_DEF "(?(DEFINE)(?(?x: (?: [0-9] | [1-9][0-9] | 1[0-9]{2} | 2[0-4][0-9] | 25[0-5] ) (?! [0-9] ) )))" 70 | 71 | /* IPV4: Decimal IPv4, e.g. "1.2.3.4", with lookahead (implemented in S4) at the end so that we don't match "192.168.1.123" in the string "192.168.1.1234". */ 72 | #define IPV4_DEF S4_DEF "(?(DEFINE)(?(?x: (?: (?&S4) \\. ){3} (?&S4) )))" 73 | 74 | /* IPv6, including embedded IPv4, e.g. "::1", "dead:beef::1.2.3.4". 75 | * Lookahead for the next char not being a dot or digit, so it doesn't get stuck matching "dead:beef::1" in "dead:beef::1.2.3.4". 76 | * This is not required since the surrounding brackets would trigger backtracking, but it allows nicer unittesting. 77 | * TODO: more strict check (right number of colons, etc.) 78 | * TODO: add zone_id: RFC 4007 section 11, RFC 6874 */ 79 | 80 | /* S6: IPv6 segment, S6C: IPv6 segment followed by a comma, CS6: comma followed by an IPv6 segment */ 81 | #define S6_DEF "(?(DEFINE)(?[[:xdigit:]]{1,4})(?:(?&S6))(?(?&S6):))" 82 | 83 | /* No :: shorthand */ 84 | #define IPV6_FULL "(?x: (?&S6C){7} (?&S6) )" 85 | /* Begins with :: */ 86 | #define IPV6_LEFT "(?x: : (?&CS6){1,7} )" 87 | /* :: somewhere in the middle - use negative lookahead to make sure there aren't too many colons in total */ 88 | #define IPV6_MID "(?x: (?! (?: [[:xdigit:]]*: ){8} ) (?&S6C){1,6} (?&CS6){1,6} )" 89 | /* Ends with :: */ 90 | #define IPV6_RIGHT "(?x: (?&S6C){1,7} : )" 91 | /* Is "::" and nothing more */ 92 | #define IPV6_NULL "(?x: :: )" 93 | 94 | /* The same ones for IPv4-embedded notation, without the actual IPv4 part */ 95 | #define IPV6V4_FULL "(?x: (?&S6C){6} )" 96 | #define IPV6V4_LEFT "(?x: :: (?&S6C){0,5} )" /* includes "::" */ 97 | #define IPV6V4_MID "(?x: (?! (?: [[:xdigit:]]*: ){7} ) (?&S6C){1,4} (?&CS6){1,4} ) :" 98 | #define IPV6V4_RIGHT "(?x: (?&S6C){1,5} : )" 99 | 100 | /* IPV6: An IPv6 address (possibly with an embedded IPv4). 101 | * This macro defines both IPV4 and IPV6, since the latter one requires the former. */ 102 | #define IP_DEF IPV4_DEF S6_DEF "(?(DEFINE)(?(?x: (?: " IPV6_NULL " | " IPV6_LEFT " | " IPV6_MID " | " IPV6_RIGHT " | " IPV6_FULL " | (?: " IPV6V4_FULL " | " IPV6V4_LEFT " | " IPV6V4_MID " | " IPV6V4_RIGHT " ) (?&IPV4) ) (?! [.:[:xdigit:]] ) )))" 103 | 104 | /* Either an alphanumeric character or dash; or if [negative lookahead] not ASCII 105 | * then any graphical Unicode character. 106 | * A segment can consist entirely of numbers. 107 | * (Note: PCRE doesn't support character class subtraction/intersection.) */ 108 | #define HOSTNAMESEGMENTCHARS_CLASS "(?x: [-[:alnum:]] | (?! [[:ascii:]] ) [[:graph:]] )" 109 | 110 | /* A hostname of at least 1 component. The last component cannot be entirely numbers. 111 | * E.g. "foo", "example.com", "1234.com", but not "foo.123" */ 112 | #define HOSTNAME1 "(?x: (?: " HOSTNAMESEGMENTCHARS_CLASS "+ \\. )* " HOSTNAMESEGMENTCHARS_CLASS "* (?! [0-9] ) " HOSTNAMESEGMENTCHARS_CLASS "+ )" 113 | 114 | /* A hostname of at least 2 components. The last component cannot be entirely numbers. 115 | * E.g. "example.com", "1234.com", but not "1234.56" */ 116 | #define HOSTNAME2 "(?x: (?: " HOSTNAMESEGMENTCHARS_CLASS "+ \\.)+ " HOSTNAME1 " )" 117 | 118 | /* For URL: Hostname, IPv4, or bracket-enclosed IPv6, e.g. "example.com", "1.2.3.4", "[::1]" */ 119 | #define URL_HOST "(?x: " HOSTNAME1 " | (?&IPV4) | \\[ (?&IPV6) \\] )" 120 | 121 | /* For e-mail: Hostname of at least two segments, or bracket-enclosed IPv4 or IPv6, e.g. "example.com", "[1.2.3.4]", "[::1]". 122 | * Technically an e-mail with a single-component hostname might be valid on a local network, but let's avoid tons of false positives (e.g. in a typical shell prompt). */ 123 | #define EMAIL_HOST "(?x: " HOSTNAME2 " | \\[ (?: (?&IPV4) | (?&IPV6) ) \\] )" 124 | 125 | /* Number between 1 and 65535, with lookahead at the end so that we don't match "6789" in the string "67890", 126 | and in turn we don't eventually match "http://host:6789" in "http://host:67890". */ 127 | #define N_1_65535 "(?x: (?: [1-9][0-9]{0,3} | [1-5][0-9]{4} | 6[0-4][0-9]{3} | 65[0-4][0-9]{2} | 655[0-2][0-9] | 6553[0-5] ) (?! [0-9] ) )" 128 | 129 | /* Optional colon-prefixed port, e.g. ":1080", "" */ 130 | #define PORT "(?x: \\:" N_1_65535 " )?" 131 | 132 | /* Omit the parentheses, see below */ 133 | #define PATHCHARS_CLASS "[-[:alnum:]\\Q_$.+!*,:;@&=?/~#|%'\\E]" 134 | /* Chars to end a URL. Apostrophe only allowed if there wasn't one in front of the URL, see bug 448044 */ 135 | #define PATHTERM_CLASS "[-[:alnum:]\\Q_$+*:@&=/~#|%'\\E]" 136 | #define PATHTERM_NOAPOS_CLASS "[-[:alnum:]\\Q_$+*:@&=/~#|%\\E]" 137 | 138 | /* Recursive definition of PATH that allows parentheses and square brackets only if balanced, see bug 763980. */ 139 | #define PATH_INNER_DEF "(?(DEFINE)(?(?x: (?: " PATHCHARS_CLASS "* (?: \\( (?&PATH_INNER) \\) | \\[ (?&PATH_INNER) \\] ) )* " PATHCHARS_CLASS "* )))" 140 | /* Same as above, but the last character (if exists and is not a parenthesis) must be from PATHTERM_CLASS. */ 141 | #define PATH_DEF "(?(DEFINE)(?(?x: (?: " PATHCHARS_CLASS "* (?: \\( (?&PATH_INNER) \\) | \\[ (?&PATH_INNER) \\] ) )* (?: " PATHCHARS_CLASS "* (?()" PATHTERM_NOAPOS_CLASS "|" PATHTERM_CLASS ") )? )))" 142 | 143 | #define URLPATH "(?x: /(?&PATH) )?" 144 | 145 | #define DEFS APOS_START_DEF IP_DEF PATH_INNER_DEF PATH_DEF 146 | 147 | #define REGEX_URL_AS_IS DEFS SCHEME "://" USERPASS URL_HOST PORT URLPATH 148 | /* TODO: also support file:/etc/passwd */ 149 | #define REGEX_URL_FILE DEFS "(?ix: file:/ (?: / (?: " HOSTNAME1 " )? / )? (?! / ) )(?&PATH)" 150 | /* Lookbehind so that we don't catch "abc.www.foo.bar", bug 739757. Lookahead for www/ftp for convenience (so that we can reuse HOSTNAME1). */ 151 | /* The commented-out variant looks more like our other definitions, but fails with PCRE 10.34. See GNOME/gnome-terminal#221. 152 | * TODO: revert to this nicer pattern some time after 10.35's release. 153 | * #define REGEX_URL_HTTP DEFS "(?. 16 | */ 17 | 18 | #include "tilda-search-box.h" 19 | #include "tilda-enum-types.h" 20 | 21 | #define PCRE2_CODE_UNIT_WIDTH 0 22 | #include 23 | 24 | #define GRESOURCE "/org/tilda/" 25 | 26 | struct _TildaSearchBox 27 | { 28 | GtkBox parent; 29 | 30 | GtkWidget *label; 31 | GtkWidget *entry; 32 | GtkWidget *button_next; 33 | GtkWidget *button_prev; 34 | GtkWidget *check_match_case; 35 | GtkWidget *check_regex; 36 | 37 | TildaSearchDirection last_direction; 38 | gboolean last_search_successful; 39 | }; 40 | 41 | enum 42 | { 43 | SIGNAL_SEARCH, 44 | SIGNAL_SEARCH_GREGEX, 45 | SIGNAL_FOCUS_OUT, 46 | 47 | LAST_SIGNAL 48 | }; 49 | 50 | static guint signals[LAST_SIGNAL] = { 0 }; 51 | 52 | G_DEFINE_TYPE (TildaSearchBox, tilda_search_box, GTK_TYPE_BOX) 53 | 54 | static void 55 | search_vte_regex (TildaSearchBox *search, 56 | TildaSearchDirection direction) 57 | { 58 | GtkEntry *entry; 59 | GtkEntryBuffer *buffer; 60 | GtkToggleButton *toggle_button; 61 | 62 | guint32 compile_flags; 63 | gboolean wrap_on_search; 64 | gboolean is_regex; 65 | gboolean match_case; 66 | const gchar *text; 67 | gchar *pattern; 68 | size_t pattern_length; 69 | gboolean search_result; 70 | 71 | GError *error; 72 | VteRegex *regex; 73 | 74 | compile_flags = 0; 75 | wrap_on_search = FALSE; 76 | toggle_button = GTK_TOGGLE_BUTTON (search->check_regex); 77 | is_regex = gtk_toggle_button_get_active (toggle_button); 78 | entry = GTK_ENTRY (search->entry); 79 | buffer = GTK_ENTRY_BUFFER (gtk_entry_get_buffer (entry)); 80 | text = gtk_entry_buffer_get_text (buffer); 81 | 82 | if (!search->last_search_successful) 83 | wrap_on_search = TRUE; 84 | 85 | if (is_regex) 86 | { 87 | compile_flags |= PCRE2_MULTILINE; 88 | pattern = g_strdup (text); 89 | } 90 | else 91 | pattern = g_regex_escape_string (text, -1); 92 | 93 | pattern_length = strlen (pattern); 94 | 95 | toggle_button = GTK_TOGGLE_BUTTON (search->check_match_case); 96 | match_case = gtk_toggle_button_get_active (toggle_button); 97 | 98 | if (!match_case) 99 | { 100 | compile_flags |= PCRE2_CASELESS; 101 | } 102 | 103 | compile_flags |= PCRE2_MULTILINE; 104 | 105 | error = NULL; 106 | 107 | regex = vte_regex_new_for_search (pattern, pattern_length, compile_flags, &error); 108 | 109 | g_free (pattern); 110 | 111 | if (error) 112 | { 113 | GtkLabel *label = GTK_LABEL (search->label); 114 | gtk_label_set_text (label, error->message); 115 | gtk_widget_set_visible (search->label, TRUE); 116 | g_error_free (error); 117 | return; 118 | } 119 | 120 | g_signal_emit (search, signals[SIGNAL_SEARCH], 0, 121 | regex, direction, wrap_on_search, &search_result); 122 | 123 | search->last_direction = direction; 124 | 125 | gtk_widget_set_visible (search->label, !search_result); 126 | search->last_search_successful = search_result; 127 | 128 | vte_regex_unref (regex); 129 | } 130 | 131 | static void 132 | search (TildaSearchBox *search, 133 | TildaSearchDirection direction) 134 | { 135 | search_vte_regex (search, direction); 136 | } 137 | 138 | static gboolean 139 | entry_key_press_cb (TildaSearchBox *box, 140 | GdkEvent *event, 141 | GtkWidget *widget) 142 | { 143 | GdkEventKey *event_key; 144 | 145 | event_key = (GdkEventKey*) event; 146 | 147 | if (event_key->keyval == GDK_KEY_Return) { 148 | search (box, box->last_direction); 149 | return GDK_EVENT_STOP; 150 | } 151 | 152 | /* If the search entry has focus the user can hide the search bar by pressing escape. */ 153 | if (event_key->keyval == GDK_KEY_Escape) 154 | { 155 | if (gtk_widget_has_focus (box->entry)) 156 | { 157 | g_signal_emit (box, signals[SIGNAL_FOCUS_OUT], 0); 158 | gtk_widget_set_visible (GTK_WIDGET (box), FALSE); 159 | 160 | return GDK_EVENT_STOP; 161 | } 162 | } 163 | 164 | return GDK_EVENT_PROPAGATE; 165 | } 166 | 167 | static gboolean 168 | entry_changed_cb (TildaSearchBox *box, 169 | GtkEditable *editable) 170 | { 171 | gtk_widget_hide (box->label); 172 | box->last_search_successful = TRUE; 173 | 174 | return GDK_EVENT_STOP; 175 | } 176 | 177 | static void 178 | button_next_cb (TildaSearchBox *box, 179 | GtkWidget *widget) 180 | { 181 | /* The default is to search forward */ 182 | search (box, SEARCH_FORWARD); 183 | } 184 | 185 | static void 186 | button_prev_cb (TildaSearchBox *box, 187 | GtkWidget *widget) 188 | { 189 | search (box, SEARCH_BACKWARD); 190 | } 191 | 192 | void 193 | tilda_search_box_toggle (TildaSearchBox *box) 194 | { 195 | gboolean visible = !gtk_widget_get_visible(GTK_WIDGET (box)); 196 | 197 | if (visible) 198 | gtk_widget_grab_focus (box->entry); 199 | else 200 | g_signal_emit (box, signals[SIGNAL_FOCUS_OUT], 0); 201 | 202 | gtk_widget_set_visible(GTK_WIDGET (box), visible); 203 | } 204 | 205 | static void 206 | tilda_search_box_class_init (TildaSearchBoxClass *box_class) 207 | { 208 | GtkWidgetClass *widget_class; 209 | const gchar *resource_name; 210 | 211 | widget_class = GTK_WIDGET_CLASS (box_class); 212 | 213 | /** 214 | * TildaSearchBox::search: 215 | * @widget: the widget that received the signal 216 | * @regex: the regular expression entered by the user 217 | * @direction: the direction for the search 218 | * @wrap_over: if the search should wrap over 219 | * 220 | * This signal is, emitted when the user performed a search action, such 221 | * as clicking on the prev or next buttons or hitting enter. 222 | * 223 | * This widget does not actually perform the search, but leaves it to the 224 | * users of this signal to perform the search based on the information 225 | * provided to the signal handler. 226 | * 227 | * The user function needs to return %TRUE or %FALSE depending on 228 | * whether the search was successful (i.e. a match was found). 229 | * 230 | * Returns: %TRUE if the search found a match, %FALSE otherwise. 231 | */ 232 | signals[SIGNAL_SEARCH] = 233 | g_signal_new ("search", TILDA_TYPE_SEARCH_BOX, G_SIGNAL_RUN_LAST, 0, 234 | NULL, NULL, NULL, G_TYPE_BOOLEAN, 235 | 3, VTE_TYPE_REGEX, TILDA_TYPE_SEARCH_DIRECTION, G_TYPE_BOOLEAN); 236 | 237 | /** 238 | * TildaSearchBox::search-gregex: 239 | * @widget: the widget that received the signal 240 | * @regex: the regular expression entered by the user 241 | * @direction: the direction for the search 242 | * @wrap_over: if the search should wrap over 243 | * 244 | * This signal is, emitted when the user performed a search action, such 245 | * as clicking on the prev or next buttons or hitting enter. 246 | * 247 | * This widget does not actually perform the search, but leaves it to the 248 | * users of this signal to perform the search based on the information 249 | * provided to the signal handler. 250 | * 251 | * The user function needs to return %TRUE or %FALSE depending on 252 | * whether the search was successful (i.e. a match was found). 253 | * 254 | * Returns: %TRUE if the search found a match, %FALSE otherwise. 255 | */ 256 | signals[SIGNAL_SEARCH_GREGEX] = 257 | g_signal_new ("search-gregex", TILDA_TYPE_SEARCH_BOX, G_SIGNAL_RUN_LAST, 0, 258 | NULL, NULL, NULL, G_TYPE_BOOLEAN, 259 | 3, G_TYPE_REGEX, TILDA_TYPE_SEARCH_DIRECTION, G_TYPE_BOOLEAN); 260 | 261 | /** 262 | * TildaSearchBox::focus-out: 263 | * @widget: the widget that received the signal 264 | * 265 | * This signal is emitted, when the search bar is being toggled 266 | * and this would cause the search bar to hide. Hiding the search bar 267 | * means that it will loose focus and that some other widget should get 268 | * focused. 269 | * 270 | * This signal should be used to grab the focus of another widget. 271 | */ 272 | signals[SIGNAL_FOCUS_OUT] = 273 | g_signal_new ("focus-out", TILDA_TYPE_SEARCH_BOX, G_SIGNAL_RUN_LAST, 0, 274 | NULL, NULL, NULL, G_TYPE_NONE, 0); 275 | 276 | resource_name = GRESOURCE "tilda-search-box.ui"; 277 | gtk_widget_class_set_template_from_resource (widget_class, resource_name); 278 | 279 | gtk_widget_class_bind_template_child (widget_class, TildaSearchBox, 280 | label); 281 | gtk_widget_class_bind_template_child (widget_class, TildaSearchBox, 282 | entry); 283 | gtk_widget_class_bind_template_child (widget_class, TildaSearchBox, 284 | button_next); 285 | gtk_widget_class_bind_template_child (widget_class, TildaSearchBox, 286 | button_prev); 287 | gtk_widget_class_bind_template_child (widget_class, TildaSearchBox, 288 | check_match_case); 289 | gtk_widget_class_bind_template_child (widget_class, TildaSearchBox, 290 | check_regex); 291 | } 292 | 293 | static void 294 | tilda_search_box_init (TildaSearchBox *box) 295 | { 296 | TildaSearchBox *search_box; 297 | 298 | gtk_widget_init_template (GTK_WIDGET (box)); 299 | 300 | search_box = TILDA_SEARCH_BOX (box); 301 | 302 | search_box->last_direction = SEARCH_BACKWARD; 303 | 304 | /* Initialize to true to prevent search from 305 | * wrapping around on first search. */ 306 | search_box->last_search_successful = TRUE; 307 | 308 | gtk_widget_set_name (GTK_WIDGET (search_box), "search"); 309 | 310 | g_signal_connect_swapped (G_OBJECT(search_box->entry), "key-press-event", 311 | G_CALLBACK(entry_key_press_cb), search_box); 312 | g_signal_connect_swapped (G_OBJECT (search_box->entry), "changed", 313 | G_CALLBACK (entry_changed_cb), search_box); 314 | g_signal_connect_swapped (G_OBJECT (search_box->button_next), "clicked", 315 | G_CALLBACK (button_next_cb), search_box); 316 | g_signal_connect_swapped (G_OBJECT (search_box->button_prev), "clicked", 317 | G_CALLBACK (button_prev_cb), search_box); 318 | } 319 | 320 | GtkWidget* 321 | tilda_search_box_new (void) 322 | { 323 | return g_object_new (TILDA_TYPE_SEARCH_BOX, 324 | "orientation", GTK_ORIENTATION_VERTICAL, 325 | NULL); 326 | } 327 | -------------------------------------------------------------------------------- /src/tilda-search-box.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Sebastian Geiger 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #ifndef TILDA_SEARCH_BOX_H 19 | #define TILDA_SEARCH_BOX_H 20 | 21 | #include 22 | #include 23 | 24 | G_BEGIN_DECLS 25 | 26 | #define TILDA_TYPE_SEARCH_BOX tilda_search_box_get_type () 27 | G_DECLARE_FINAL_TYPE (TildaSearchBox, tilda_search_box, TILDA, SEARCH_BOX, GtkBox); 28 | 29 | typedef enum { 30 | SEARCH_FORWARD, 31 | SEARCH_BACKWARD 32 | } TildaSearchDirection; 33 | 34 | GtkWidget *tilda_search_box_new (void); 35 | 36 | /** 37 | * Toggles the visibility of the search box. 38 | * 39 | * If this causes the search box to be made visible, then the search entry 40 | * widget will be focused. 41 | * 42 | * Otherwise if the search box was visible and will be hidden now, then the 43 | * ::focus-out signal will be emitted. Users of this widget can connect to 44 | * the ::focus-out signal and use it focus another widget instead. 45 | */ 46 | void tilda_search_box_toggle (TildaSearchBox *box); 47 | 48 | G_END_DECLS 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /src/tilda-search-box.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 118 | 119 | -------------------------------------------------------------------------------- /src/tilda-url-spawner.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free software; you can redistribute it and/or modify it under 3 | * the terms of the GNU Library General Public License as published by 4 | * the Free Software Foundation; either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, but 8 | * WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Library General Public 13 | * License along with this library. If not, see . 14 | */ 15 | 16 | #include "tilda-url-spawner.h" 17 | 18 | #include 19 | 20 | #include "configsys.h" 21 | #include "debug.h" 22 | 23 | void launch_configured_web_browser (const char * match); 24 | 25 | void tilda_url_spawner_spawn_browser_for_match (GtkWindow * parent, 26 | const gchar * match, 27 | TildaMatchRegistryEntry * entry) 28 | { 29 | gchar * uri; 30 | TildaMatchRegistryFlavor flavor; 31 | 32 | if (match == NULL) 33 | return; 34 | 35 | flavor = tilda_match_registry_entry_get_flavor (entry); 36 | 37 | if (flavor == TILDA_MATCH_FLAVOR_URL || 38 | flavor == TILDA_MATCH_FLAVOR_DEFAULT_TO_HTTP) 39 | { 40 | /* Starting with version 1.6 and above by default tilda uses 41 | * the gtk_show_uri function family to open URIs, this option 42 | * allows to go back to the legacy behavior and use a configured 43 | * command to spawn a browser. We will eventually remove this option. */ 44 | gboolean use_custom_web_browser = config_getbool("use_custom_web_browser"); 45 | 46 | if (use_custom_web_browser) { 47 | launch_configured_web_browser (match); 48 | return; 49 | } 50 | } 51 | 52 | if (!tilda_match_registry_flavor_is_uri(entry)) { 53 | return; 54 | } 55 | 56 | uri = tilda_match_registry_entry_get_uri_from_match (entry, match); 57 | 58 | if (uri == NULL) { 59 | g_debug ("Url not opened, because match flavor is unknown."); 60 | 61 | return; 62 | } 63 | 64 | GError * error = NULL; 65 | 66 | gtk_show_uri_on_window(parent, uri, GDK_CURRENT_TIME, &error); 67 | 68 | if (error != NULL) { 69 | g_critical("Unable to open URI: %s", error->message); 70 | g_error_free(error); 71 | } 72 | 73 | g_free (uri); 74 | } 75 | 76 | void launch_configured_web_browser (const char * match) 77 | { 78 | gchar * cmd; 79 | gchar * web_browser_cmd; 80 | gboolean result; 81 | 82 | web_browser_cmd = g_strescape (config_getstr ("web_browser"), NULL); 83 | cmd = g_strdup_printf ("%s %s", web_browser_cmd, match); 84 | 85 | g_debug ("Launching command: `%s'", cmd); 86 | 87 | result = g_spawn_command_line_async (cmd, NULL); 88 | 89 | /* Check that the command launched */ 90 | if (!result) 91 | { 92 | g_critical (_("Failed to launch the web browser. The command was `%s'\n"), cmd); 93 | TILDA_PERROR (); 94 | } 95 | 96 | g_free (web_browser_cmd); 97 | g_free (cmd); 98 | } 99 | -------------------------------------------------------------------------------- /src/tilda-url-spawner.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free software; you can redistribute it and/or modify it under 3 | * the terms of the GNU Library General Public License as published by 4 | * the Free Software Foundation; either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, but 8 | * WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Library General Public 13 | * License along with this library. If not, see . 14 | */ 15 | 16 | #ifndef TILDA_URL_SPAWNER_H 17 | #define TILDA_URL_SPAWNER_H 18 | 19 | #include 20 | 21 | #include "tilda-match-registry.h" 22 | 23 | void tilda_url_spawner_spawn_browser_for_match (GtkWindow * parent, 24 | const gchar * match, 25 | TildaMatchRegistryEntry * entry); 26 | 27 | #endif // TILDA_URL_SPAWNER_H 28 | -------------------------------------------------------------------------------- /src/tilda.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free software; you can redistribute it and/or modify it under 3 | * the terms of the GNU Library General Public License as published by 4 | * the Free Software Foundation; either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, but 8 | * WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Library General Public 13 | * License along with this library. If not, see . 14 | */ 15 | 16 | #ifndef TILDA_H 17 | #define TILDA_H 18 | 19 | #include 20 | 21 | G_BEGIN_DECLS 22 | 23 | #define TILDA_VERSION PACKAGE_NAME " " PACKAGE_VERSION 24 | 25 | #define GUINT16_TO_FLOAT(color) ((color) / (double) 0xFFFF) 26 | #define GUINT16_FROM_FLOAT(value) ((int) ((value) * 0xFFFF + 0.5)) 27 | 28 | #define RGB(r,g,b) (r) / (gdouble)G_MAXUINT16, \ 29 | (g) / (gdouble)G_MAXUINT16, \ 30 | (b) / (gdouble)G_MAXUINT16, 1. 31 | 32 | G_END_DECLS 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/tilda_terminal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free software; you can redistribute it and/or modify it under 3 | * the terms of the GNU Library General Public License as published by 4 | * the Free Software Foundation; either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, but 8 | * WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Library General Public 13 | * License along with this library. If not, see . 14 | */ 15 | 16 | #ifndef TILDA_TERMINALN_H 17 | #define TILDA_TERMINALN_H 18 | 19 | #include "tilda_window.h" 20 | #include "tilda-palettes.h" 21 | #include "tilda-match-registry.h" 22 | 23 | #include 24 | #include 25 | 26 | G_BEGIN_DECLS 27 | 28 | typedef struct tilda_term_ tilda_term; 29 | 30 | struct tilda_term_ 31 | { 32 | GtkWidget *vte_term; 33 | GtkWidget *hbox; 34 | GtkWidget *scrollbar; 35 | GRegex *http_regexp; 36 | VteRegex *vte_regexp; 37 | TildaMatchRegistry * registry; 38 | GPid pid; 39 | /* We remember if we have already dropped to the default 40 | * shell before, if so, then we know that this time we can 41 | * exit the program. 42 | */ 43 | gboolean dropped_to_default_shell; 44 | gchar *initial_working_dir; 45 | 46 | struct tilda_window_ *tw; 47 | }; 48 | 49 | enum tilda_term_scrollbar_positions { RIGHT, LEFT, DISABLED }; 50 | enum delete_keys { ASCII_DELETE, DELETE_SEQUENCE, ASCII_BACKSPACE, AUTO }; 51 | 52 | /** 53 | * tilda_term_init () 54 | * 55 | * Initialize and return a new struct tilda_term_. 56 | * 57 | * @param tw The main tilda window, which must be initialized. 58 | * 59 | * @param index The location to insert the terminal. If this is negative, or is 60 | * larger than the current number of terminals, the new terminal is added on to 61 | * the end of the list. 62 | * 63 | * Success: return a non-NULL struct tilda_term_ *. 64 | * Failure: return NULL. 65 | * 66 | * Notes: you must call tilda_term_free() on the returned struct tilda_term_ 67 | * when you are finished using it, and it has been removed from all GTK 68 | * structures, such as the notebook. 69 | */ 70 | struct tilda_term_ *tilda_term_init (struct tilda_window_ *tw, gint position); 71 | 72 | /** 73 | * tilda_term_free () 74 | * 75 | * Free a struct tilda_term_* created with tilda_term_init (). This will 76 | * clean up any memory allocations that were made to create the object. It 77 | * should only be called when there is no more need to access the object. 78 | * 79 | * Success: return 0 80 | * Failure: return non-zero 81 | */ 82 | gint tilda_term_free (struct tilda_term_ *term); 83 | 84 | 85 | void tilda_term_set_scrollbar_position (tilda_term *tt, enum tilda_term_scrollbar_positions pos); 86 | char* tilda_term_get_cwd(tilda_term* tt); 87 | 88 | 89 | /* Adjust the font-size scale for the terminal */ 90 | void tilda_term_adjust_font_scale(tilda_term *term, gdouble scale); 91 | 92 | gchar * tilda_terminal_get_full_title (tilda_term *tt); 93 | gchar * tilda_terminal_get_title (tilda_term *tt); 94 | 95 | void tilda_terminal_update_matches (tilda_term *tt); 96 | 97 | #define TILDA_TERM(tt) ((tilda_term *)(tt)) 98 | 99 | G_END_DECLS 100 | 101 | /* vim: set ts=4 sts=4 sw=4 expandtab: */ 102 | 103 | #endif /* TILDA_TERMINALN_H */ 104 | 105 | -------------------------------------------------------------------------------- /src/tilda_window.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free software; you can redistribute it and/or modify it under 3 | * the terms of the GNU Library General Public License as published by 4 | * the Free Software Foundation; either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, but 8 | * WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Library General Public 13 | * License along with this library. If not, see . 14 | */ 15 | 16 | #ifndef TILDA_WINDOW_H 17 | #define TILDA_WINDOW_H 18 | 19 | #include "tilda_terminal.h" 20 | 21 | #include 22 | #include 23 | 24 | #include "tilda-search-box.h" 25 | 26 | G_BEGIN_DECLS 27 | 28 | enum pull_action { 29 | PULL_UP, 30 | PULL_DOWN, 31 | PULL_TOGGLE 32 | }; 33 | 34 | typedef struct tilda_window_ tilda_window; 35 | 36 | enum tilda_animation_state { 37 | STATE_UP, 38 | STATE_DOWN, 39 | STATE_GOING_UP, 40 | STATE_GOING_DOWN 41 | }; 42 | 43 | struct tilda_window_ 44 | { 45 | GtkWidget *window; 46 | GtkWidget *notebook; 47 | GtkWidget *search; 48 | 49 | GList *terms; 50 | GtkAccelGroup * accel_group; 51 | GtkBuilder *gtk_builder; 52 | GtkWidget *wizard_window; /* GtkDialog that contains the wizard */ 53 | 54 | gchar *lock_file; 55 | gchar *config_file; 56 | gboolean config_writing_disabled; 57 | gint instance; 58 | gboolean have_argb_visual; 59 | 60 | /* Temporarily disable auto hiding */ 61 | gboolean disable_auto_hide; 62 | /* Auto hide tick-function handler */ 63 | guint auto_hide_tick_handler; 64 | /* Auto hide current time */ 65 | guint32 auto_hide_current_time; 66 | /* Auto hide max time */ 67 | guint32 auto_hide_max_time; 68 | /* Generic timer resolution */ 69 | guint32 timer_resolution; 70 | /* Should Tilda hide itself on focus lost event? */ 71 | gboolean auto_hide_on_focus_lost; 72 | /* Should Tilda hide itself when mouse leaves it? */ 73 | gboolean auto_hide_on_mouse_leave; 74 | 75 | /* Should Tilda hide itself even if not focused */ 76 | gboolean hide_non_focused; 77 | 78 | gboolean fullscreen; 79 | 80 | /* If tilda was started with D-Bus support */ 81 | gboolean dbus_enabled; 82 | 83 | /* This field MUST be set before calling pull()! */ 84 | enum tilda_animation_state current_state; 85 | 86 | gboolean focus_loss_on_keypress; 87 | 88 | gint unscaled_font_size; 89 | gdouble current_scale_factor; 90 | 91 | enum pull_action last_action; 92 | gint64 last_action_time; 93 | 94 | /** 95 | * This stores the ID of the event source which handles size updates. 96 | */ 97 | guint size_update_event_source; 98 | }; 99 | 100 | /* For use in get_display_dimension() */ 101 | enum dimensions { HEIGHT, WIDTH }; 102 | 103 | enum notebook_tab_positions { NB_TOP, NB_BOTTOM, NB_LEFT, NB_RIGHT, NB_HIDDEN }; 104 | 105 | /** 106 | * tilda_window_add_tab () 107 | * 108 | * Create and add a new tab at the end of the notebook 109 | * 110 | * Success: the new tab's index (>=0) 111 | * Failure: -1 112 | */ 113 | gint tilda_window_add_tab (tilda_window *tw); 114 | 115 | /** 116 | * tilda_window_close_tab () 117 | * 118 | * Closes the tab at the given tab index (starting from 0) 119 | * 120 | * Success: return 0 121 | * Failure: return non-zero 122 | */ 123 | gint tilda_window_close_tab (tilda_window *tw, gint tab_position, gboolean force_exit); 124 | 125 | /** 126 | * tilda_window_next_tab () 127 | * 128 | * Switch to next tab 129 | * 130 | * Success: return 0 131 | * Failure: return non-zero 132 | */ 133 | gint tilda_window_next_tab (tilda_window *tw); 134 | 135 | /** 136 | * tilda_window_prev_tab () 137 | * 138 | * Switch to previous tab 139 | * 140 | * Success: return 0 141 | * Failure: return non-zero 142 | */ 143 | gint tilda_window_prev_tab (tilda_window *tw); 144 | 145 | /** 146 | * tilda_window_init () 147 | * 148 | * Initializes an already allocated tilda_window *. It will also initialize and set up 149 | * as much of the window as possible using the values in the configuration system. 150 | * 151 | * @param instance the instance number of this tilda_window 152 | * 153 | * Notes: The configuration system must be up and running before calling this function. 154 | */ 155 | gboolean tilda_window_init (const gchar *config_file, const gint instance, tilda_window *tw); 156 | 157 | /** 158 | * Releases resources that are being used by the tilda window, such as the tabs 159 | * or the config file. 160 | */ 161 | gint tilda_window_free (tilda_window *tw); 162 | 163 | /** 164 | * Applies or reapplies the current fullscreen state of the tilda window. 165 | */ 166 | void tilda_window_set_fullscreen(tilda_window *tw); 167 | 168 | /** 169 | * This toggles the fullscreen mode on or off. This is intended to be registered 170 | * as a GCallback in order to be invoked after some user action. 171 | */ 172 | gint toggle_fullscreen_cb (tilda_window *tw); 173 | 174 | /** 175 | * Set the D-Bus state in the tilda window, to indicate if D-Bus is enabled. 176 | * @param tw An instance of a tilda_window struct. 177 | * @param enabled TRUE if D-Bus is enabled for this instance, false otherwise. 178 | */ 179 | void tilda_window_set_dbus_enabled (tilda_window *tw, gboolean enabled); 180 | 181 | /** 182 | * Get the D-Bus state in the tilda window. 183 | * @param tw An instance of a tilda_window struct.q 184 | * @return Returns TRUE if D-Bus is enabled, FALSE otherwise. 185 | */ 186 | gboolean tilda_window_get_dbus_enabled (tilda_window *tw); 187 | 188 | /** 189 | * This controls where the tabs are positions (e.g. top, left, bottom or 190 | * right). 191 | */ 192 | gint tilda_window_set_tab_position (tilda_window *tw, enum notebook_tab_positions pos); 193 | 194 | /** 195 | * tilda_window_close_tab () 196 | * 197 | * Closes the tab current tab 198 | */ 199 | void tilda_window_close_current_tab (tilda_window *tw); 200 | 201 | /* This should be called by the wizard for each key that has changed. */ 202 | gboolean tilda_window_update_keyboard_accelerators (const gchar* path, const gchar* value); 203 | 204 | /** 205 | * Toggles transparency on all terms 206 | */ 207 | void tilda_window_toggle_transparency(tilda_window *tw); 208 | 209 | /** 210 | * Refreshes transparency 211 | */ 212 | void tilda_window_refresh_transparency(tilda_window *tw); 213 | 214 | /** 215 | * Toggles the search bar of the tilda window. 216 | */ 217 | void tilda_window_toggle_searchbar (tilda_window *tw); 218 | 219 | /** 220 | * Show confirm dialog before quitting (if enabled) 221 | */ 222 | gint tilda_window_confirm_quit (tilda_window *tw); 223 | 224 | GdkMonitor* tilda_window_find_monitor_number(tilda_window *tw); 225 | 226 | /** 227 | * Finds the coordinate that will center the tilda window in the screen. 228 | * 229 | * If you want to center the tilda window on the top or bottom of the screen, 230 | * pass the screen width into screen_dimension and the tilda window's width 231 | * into the tilda_dimension variable. The result will be the x coordinate that 232 | * should be used in order to have the tilda window centered on the screen. 233 | * 234 | * Centering based on y coordinate is similar, just use the screen height and 235 | * tilda window height. 236 | */ 237 | gint tilda_window_find_centering_coordinate (tilda_window *tw, enum dimensions dimension); 238 | 239 | void tilda_window_update_window_position (tilda_window *tw); 240 | 241 | #define TILDA_WINDOW(data) ((tilda_window *)(data)) 242 | 243 | /* Allow scales a bit smaller and a bit larger than the usual pango ranges */ 244 | #define TERMINAL_SCALE_XXX_SMALL (PANGO_SCALE_XX_SMALL/1.2) 245 | #define TERMINAL_SCALE_XXXX_SMALL (TERMINAL_SCALE_XXX_SMALL/1.2) 246 | #define TERMINAL_SCALE_XXXXX_SMALL (TERMINAL_SCALE_XXXX_SMALL/1.2) 247 | #define TERMINAL_SCALE_XXX_LARGE (PANGO_SCALE_XX_LARGE*1.2) 248 | #define TERMINAL_SCALE_XXXX_LARGE (TERMINAL_SCALE_XXX_LARGE*1.2) 249 | #define TERMINAL_SCALE_XXXXX_LARGE (TERMINAL_SCALE_XXXX_LARGE*1.2) 250 | #define TERMINAL_SCALE_MINIMUM (TERMINAL_SCALE_XXXXX_SMALL/1.2) 251 | #define TERMINAL_SCALE_MAXIMUM (TERMINAL_SCALE_XXXXX_LARGE*1.2) 252 | 253 | G_END_DECLS 254 | 255 | #endif 256 | -------------------------------------------------------------------------------- /src/tomboykeybinder.c: -------------------------------------------------------------------------------- 1 | /* tomboykeybinder.c 2 | * Copyright (C) 2008 Alex Graveley 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "eggaccelerators.h" 32 | #include "tomboykeybinder.h" 33 | #include "debug.h" 34 | 35 | /** 36 | * This mask corresponds to the first 8 modifier masks of GdkModifierType 37 | * and is equal to a combination of all key masks as defined in the X 38 | * Windowing system. It can be used to remove virtual modifiers from a 39 | * list of virtual and real modifiers. 40 | */ 41 | #define REAL_MODIFIER_MASK (GDK_SHIFT_MASK \ 42 | | GDK_LOCK_MASK \ 43 | | GDK_CONTROL_MASK \ 44 | | GDK_MOD1_MASK \ 45 | | GDK_MOD2_MASK \ 46 | | GDK_MOD3_MASK \ 47 | | GDK_MOD4_MASK \ 48 | | GDK_MOD5_MASK) 49 | 50 | typedef struct _Binding { 51 | TomboyBindkeyHandler handler; 52 | gpointer user_data; 53 | char *keystring; 54 | unsigned int keycode; 55 | GdkModifierType modifiers; 56 | } Binding; 57 | 58 | static GSList *bindings = NULL; 59 | static Time last_event_time = 0; 60 | static gboolean processing_event = FALSE; 61 | 62 | /** 63 | * This is used to store the real modifier values for the virtual modifiers 64 | * num lock, caps lock and scroll lock. 65 | */ 66 | static GdkModifierType num_lock_mask, caps_lock_mask, scroll_lock_mask; 67 | 68 | /** 69 | * Gdk does not allow us to determine the real modifiers for some 70 | * special virtual modifiers such as num lock and scroll look. 71 | * Therefore we will need to determine these our self. 72 | * 73 | * @param keymap 74 | */ 75 | static void 76 | lookup_ignorable_modifiers (GdkKeymap *keymap) 77 | { 78 | gchar *string; 79 | 80 | egg_keymap_resolve_virtual_modifiers (keymap, 81 | EGG_VIRTUAL_LOCK_MASK, 82 | &caps_lock_mask); 83 | 84 | string = g_flags_to_string (GDK_TYPE_MODIFIER_TYPE, caps_lock_mask); 85 | g_debug ("Virtual modifier for 'caps_lock_mask' set to: %s", string); 86 | g_free (string); 87 | 88 | egg_keymap_resolve_virtual_modifiers (keymap, 89 | EGG_VIRTUAL_NUM_LOCK_MASK, 90 | &num_lock_mask); 91 | 92 | string = g_flags_to_string (GDK_TYPE_MODIFIER_TYPE, num_lock_mask); 93 | g_debug ("Virtual modifier for 'num_lock_mask' set to: %s", string); 94 | g_free (string); 95 | 96 | egg_keymap_resolve_virtual_modifiers (keymap, 97 | EGG_VIRTUAL_SCROLL_LOCK_MASK, 98 | &scroll_lock_mask); 99 | 100 | string = g_flags_to_string (GDK_TYPE_MODIFIER_TYPE, scroll_lock_mask); 101 | g_debug ("Virtual modifier for 'scroll_lock_mask' set to: %s", string); 102 | g_free (string); 103 | } 104 | 105 | static void 106 | grab_ungrab_with_ignorable_modifiers (GdkWindow *rootwin, 107 | Binding *binding, 108 | gboolean grab) 109 | { 110 | guint mod_masks[] = { 111 | 0, /* modifier only */ 112 | num_lock_mask, 113 | caps_lock_mask, 114 | scroll_lock_mask, 115 | num_lock_mask | caps_lock_mask, 116 | num_lock_mask | scroll_lock_mask, 117 | caps_lock_mask | scroll_lock_mask, 118 | num_lock_mask | caps_lock_mask | scroll_lock_mask, 119 | }; 120 | guint i; 121 | 122 | for (i = 0; i < G_N_ELEMENTS (mod_masks); i++) { 123 | if (grab) { 124 | gdk_x11_display_error_trap_push(gdk_display_get_default()); 125 | XGrabKey (GDK_WINDOW_XDISPLAY (rootwin), 126 | binding->keycode, 127 | binding->modifiers | mod_masks[i], 128 | GDK_WINDOW_XID (rootwin), 129 | False, 130 | GrabModeAsync, 131 | GrabModeAsync); 132 | gdk_x11_display_error_trap_pop_ignored(gdk_display_get_default()); 133 | } else { 134 | gdk_x11_display_error_trap_push(gdk_display_get_default()); 135 | XUngrabKey (GDK_WINDOW_XDISPLAY (rootwin), 136 | binding->keycode, 137 | binding->modifiers | mod_masks[i], 138 | GDK_WINDOW_XID (rootwin)); 139 | gdk_x11_display_error_trap_pop_ignored(gdk_display_get_default()); 140 | } 141 | } 142 | } 143 | 144 | static gboolean 145 | do_grab_key (Binding *binding) 146 | { 147 | GdkDisplay *display = gdk_display_get_default (); 148 | GdkKeymap *keymap = gdk_keymap_get_for_display (display); 149 | GdkWindow *rootwin = gdk_get_default_root_window (); 150 | 151 | GdkModifierType virtual_mods = (GdkModifierType) 0; 152 | guint keysym = 0; 153 | 154 | if (keymap == NULL || rootwin == NULL) 155 | return FALSE; 156 | 157 | gtk_accelerator_parse (binding->keystring, 158 | &keysym, 159 | &virtual_mods); 160 | 161 | if (keysym == 0 && virtual_mods == 0) { 162 | return FALSE; 163 | } 164 | 165 | binding->keycode = XKeysymToKeycode (GDK_WINDOW_XDISPLAY (rootwin), 166 | keysym); 167 | if (binding->keycode == 0) 168 | return FALSE; 169 | 170 | GdkModifierType mapped_modifiers = virtual_mods; 171 | 172 | gdk_keymap_map_virtual_modifiers (keymap, 173 | &mapped_modifiers); 174 | 175 | // mask out virtual modifiers so we get only the real modifiers 176 | binding->modifiers = mapped_modifiers & REAL_MODIFIER_MASK; 177 | 178 | gdk_x11_display_error_trap_push (display); 179 | 180 | grab_ungrab_with_ignorable_modifiers (rootwin, 181 | binding, 182 | TRUE /* grab */); 183 | 184 | gdk_display_flush (display); 185 | 186 | if (gdk_x11_display_error_trap_pop (display)) { 187 | g_warning ("Binding '%s' failed!\n", binding->keystring); 188 | return FALSE; 189 | } 190 | 191 | gchar *virtual_modifier_string = g_flags_to_string (GDK_TYPE_MODIFIER_TYPE, 192 | virtual_mods); 193 | g_debug ("Resolved accelerator: %s. KeySymbol: %d, Virtual Modifiers: %s", 194 | binding->keystring, 195 | keysym, 196 | virtual_modifier_string); 197 | g_free (virtual_modifier_string); 198 | 199 | g_debug ("Binding to keycode %d", binding->keycode); 200 | 201 | gchar *real_modifiers_as_string = g_flags_to_string (GDK_TYPE_MODIFIER_TYPE, 202 | (GdkModifierType) binding->modifiers); 203 | g_debug ("Binding to real modifier mask %d (%s)", binding->modifiers, 204 | real_modifiers_as_string); 205 | g_free (real_modifiers_as_string); 206 | 207 | return TRUE; 208 | } 209 | 210 | static gboolean 211 | do_ungrab_key (Binding *binding) 212 | { 213 | GdkWindow *rootwin = gdk_get_default_root_window (); 214 | 215 | g_debug ("Removing grab for '%s'", binding->keystring); 216 | 217 | grab_ungrab_with_ignorable_modifiers (rootwin, 218 | binding, 219 | FALSE /* ungrab */); 220 | 221 | return TRUE; 222 | } 223 | 224 | static GdkFilterReturn 225 | filter_func (GdkXEvent *gdk_xevent, G_GNUC_UNUSED GdkEvent *event, 226 | G_GNUC_UNUSED gpointer data) 227 | { 228 | XEvent *xevent = (XEvent *) gdk_xevent; 229 | guint event_mods; 230 | GSList *iter; 231 | 232 | switch (xevent->type) { 233 | case KeyPress: 234 | g_debug ("Got KeyPress! keycode: %d, modifiers: %d", 235 | xevent->xkey.keycode, 236 | xevent->xkey.state); 237 | 238 | /* 239 | * Set the last event time for use when showing 240 | * windows to avoid anti-focus-stealing code. 241 | */ 242 | processing_event = TRUE; 243 | last_event_time = xevent->xkey.time; 244 | 245 | g_debug ("Current event time %ld", last_event_time); 246 | 247 | event_mods = xevent->xkey.state & ~(num_lock_mask | 248 | caps_lock_mask | 249 | scroll_lock_mask); 250 | 251 | for (iter = bindings; iter != NULL; iter = iter->next) { 252 | Binding *binding = (Binding *) iter->data; 253 | 254 | if (binding->keycode == xevent->xkey.keycode && 255 | binding->modifiers == event_mods) { 256 | 257 | g_debug ("Calling handler for '%s'...", 258 | binding->keystring); 259 | 260 | (binding->handler) (binding->keystring, 261 | binding->user_data); 262 | } 263 | } 264 | 265 | processing_event = FALSE; 266 | break; 267 | case KeyRelease: 268 | g_debug ("Got KeyRelease!"); 269 | break; 270 | default: 271 | break; 272 | } 273 | 274 | return GDK_FILTER_CONTINUE; 275 | } 276 | 277 | /** 278 | * This is invoked if the keymap changes, for example if some virtual 279 | * modifier are remapped to real modifiers with `xmodmap`. 280 | * 281 | * To how this function work one can set the virtual modifier 'Scroll_Lock' 282 | * to the real modifier 'mod3' and clear it again: 283 | * 284 | * xmodmap -e "add mod3 = Scroll_Lock" 285 | * xmodmap -e "clear mod3" 286 | * 287 | * This will cause this callback to be invoked. 288 | * 289 | * @param map Pointer to the current key map. 290 | */ 291 | static void 292 | keymap_changed (GdkKeymap *map) 293 | { 294 | GSList *iter; 295 | 296 | g_debug ("Keymap changed! Regrabbing keys..."); 297 | 298 | for (iter = bindings; iter != NULL; iter = iter->next) { 299 | Binding *binding = (Binding *) iter->data; 300 | do_ungrab_key (binding); 301 | } 302 | 303 | lookup_ignorable_modifiers (map); 304 | 305 | for (iter = bindings; iter != NULL; iter = iter->next) { 306 | Binding *binding = (Binding *) iter->data; 307 | do_grab_key (binding); 308 | } 309 | } 310 | 311 | void 312 | tomboy_keybinder_init (void) 313 | { 314 | GdkDisplay *display = gdk_display_get_default (); 315 | GdkKeymap *keymap = gdk_keymap_get_for_display (display); 316 | GdkWindow *rootwin = gdk_get_default_root_window (); 317 | 318 | lookup_ignorable_modifiers (keymap); 319 | 320 | gdk_window_add_filter (rootwin, 321 | filter_func, 322 | NULL); 323 | 324 | g_signal_connect (keymap, 325 | "keys_changed", 326 | G_CALLBACK (keymap_changed), 327 | NULL); 328 | } 329 | 330 | gboolean 331 | tomboy_keybinder_bind (const char *keystring, 332 | TomboyBindkeyHandler handler, 333 | gpointer user_data) 334 | { 335 | Binding *binding; 336 | gboolean success; 337 | 338 | binding = g_new0 (Binding, 1); 339 | binding->keystring = g_strdup (keystring); 340 | binding->handler = handler; 341 | binding->user_data = user_data; 342 | 343 | /* Sets the binding's keycode and modifiers */ 344 | success = do_grab_key (binding); 345 | 346 | if (success) { 347 | 348 | g_debug("Added binding. Keystring: %s", binding->keystring); 349 | 350 | bindings = g_slist_prepend (bindings, binding); 351 | } else { 352 | g_free (binding->keystring); 353 | g_free (binding); 354 | } 355 | 356 | return success; 357 | } 358 | 359 | void 360 | tomboy_keybinder_unbind (const char *keystring, 361 | TomboyBindkeyHandler handler) 362 | { 363 | GSList *iter; 364 | 365 | for (iter = bindings; iter != NULL; iter = iter->next) { 366 | Binding *binding = (Binding *) iter->data; 367 | 368 | if (strcmp (keystring, binding->keystring) != 0 || 369 | handler != binding->handler) 370 | continue; 371 | 372 | do_ungrab_key (binding); 373 | 374 | bindings = g_slist_remove (bindings, binding); 375 | 376 | g_free (binding->keystring); 377 | g_free (binding); 378 | break; 379 | } 380 | } 381 | 382 | Time 383 | tomboy_keybinder_get_current_event_time (void) 384 | { 385 | if (processing_event) 386 | return last_event_time; 387 | else 388 | return GDK_CURRENT_TIME; 389 | } 390 | -------------------------------------------------------------------------------- /src/tomboykeybinder.h: -------------------------------------------------------------------------------- 1 | /* tomboykeybinder.h 2 | * Copyright (C) 2008 Alex Graveley 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef __TOMBOY_KEY_BINDER_H__ 25 | #define __TOMBOY_KEY_BINDER_H__ 26 | 27 | #include 28 | #include 29 | 30 | G_BEGIN_DECLS 31 | 32 | typedef void (*TomboyBindkeyHandler) (char *keystring, gpointer user_data); 33 | 34 | void tomboy_keybinder_init (void); 35 | 36 | gboolean tomboy_keybinder_bind (const char *keystring, 37 | TomboyBindkeyHandler handler, 38 | gpointer user_data); 39 | 40 | void tomboy_keybinder_unbind (const char *keystring, 41 | TomboyBindkeyHandler handler); 42 | 43 | gboolean tomboy_keybinder_is_modifier (guint keycode); 44 | 45 | Time tomboy_keybinder_get_current_event_time (void); 46 | 47 | G_END_DECLS 48 | 49 | #endif /* __TOMBOY_KEY_BINDER_H__ */ 50 | 51 | -------------------------------------------------------------------------------- /src/wizard.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free software; you can redistribute it and/or modify it under 3 | * the terms of the GNU Library General Public License as published by 4 | * the Free Software Foundation; either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, but 8 | * WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Library General Public 13 | * License along with this library. If not, see . 14 | */ 15 | 16 | #ifndef WIZARD_H 17 | #define WIZARD_H 18 | 19 | #include "tilda_window.h" 20 | #include "tilda_terminal.h" 21 | 22 | #include 23 | 24 | G_BEGIN_DECLS 25 | 26 | gint wizard (tilda_window *tw); 27 | 28 | G_END_DECLS 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /tilda-dbus.desktop.in: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Tilda (D-Bus) 3 | Comment=Terminal Emulator (with D-Bus support enabled, recommended on Wayland desktops). 4 | Exec=@BINDIR@/tilda --dbus 5 | Icon=tilda 6 | Terminal=false 7 | Type=Application 8 | Categories=GNOME;GTK;System;TerminalEmulator; 9 | -------------------------------------------------------------------------------- /tilda.appdata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | tilda.desktop 5 | CC0-1.0 6 | GPL-2.0 7 | Tilda 8 | A configurable drop-down terminal 9 | 10 |

11 | Tilda is a highly-configurable terminal emulator. The specialty of Tilda is that it does not behave like a normal window but instead it can be pulled up and down from the top of the screen with a hotkey. 12 |

13 |

14 | Tilda provides support for tabs (tabbed terminals), transparency, appearance adjustments, configurable hotkeys for various functions, and other options that affect the behavior of Tilda. 15 | The screenshots show some of the options that Tilda provides. 16 |

17 |
18 | 19 | 20 | https://raw.githubusercontent.com/lanoxx/tilda/20489575e27852b58aa4c734998bcf1d5216c097/images/tilda_general-16-9.png 21 | General options 22 | 23 | 24 | https://raw.githubusercontent.com/lanoxx/tilda/20489575e27852b58aa4c734998bcf1d5216c097/images/tilda_appearance-16-9.png 25 | Appearance options 26 | 27 | 28 | https://raw.githubusercontent.com/lanoxx/tilda/20489575e27852b58aa4c734998bcf1d5216c097/images/tilda_keybindings-16-9.png 29 | Keybinding options 30 | 31 | 32 | https://raw.githubusercontent.com/lanoxx/tilda/20489575e27852b58aa4c734998bcf1d5216c097/images/tilda_title_and_command-16-9.png 33 | Title and Command options 34 | 35 | 36 | https://raw.githubusercontent.com/lanoxx/tilda/20489575e27852b58aa4c734998bcf1d5216c097/images/tilda_colors-16-9.png 37 | Title and Command options 38 | 39 | 40 | https://github.com/lanoxx/tilda 41 | lanoxx_at_gmx.net 42 |
43 | -------------------------------------------------------------------------------- /tilda.desktop.in: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Tilda 3 | Comment=Terminal Emulator 4 | Exec=@BINDIR@/tilda 5 | Icon=tilda 6 | Terminal=false 7 | Type=Application 8 | Categories=GNOME;GTK;System;TerminalEmulator; 9 | -------------------------------------------------------------------------------- /tilda.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanoxx/tilda/51bfe3c7cb755499fa22d00134d68b86a9fdaafd/tilda.png --------------------------------------------------------------------------------