Compare commits

..

No commits in common. "master" and "maint" have entirely different histories.

49 changed files with 246 additions and 1955 deletions

View File

@ -25,7 +25,6 @@ jobs:
env:
CC: ${{ matrix.CC }}
EXTRA_CFLAGS: "-Werror"
steps:
- uses: actions/checkout@v2
with:

View File

@ -1,11 +1,5 @@
# Dunst changelog
## Unreleased
### Added
### Changed
### Fixed
## 1.6.1 - 2021-02-21:
### Fixed

View File

@ -15,10 +15,6 @@
- Add the comments to the prototype. Doxygen will merge the protoype and implementation documentation anyways.
Except for **static** methods, add the documentation header to the implementation and *not to the prototype*.
- Member documentation should happen with `/**<` and should span to the right side of the member
- Test files that have the same name as a file in src/\* can include the
associated .c file. This is because they are being compiled INSTEAD of the src
file.
## Log messages

View File

@ -3,7 +3,7 @@
include config.mk
VERSION := "1.6.1-non-git"
VERSION := "1.6.1 (2021-02-21)"
ifneq ($(wildcard ./.git/),)
VERSION := $(shell ${GIT} describe --tags)
endif
@ -148,8 +148,7 @@ service-systemd:
endif
ifneq (0,${WAYLAND})
wayland-protocols: src/wayland/protocols/wlr-layer-shell-unstable-v1.xml src/wayland/protocols/wlr-foreign-toplevel-management-unstable-v1.xml
# TODO: write this shorter
wayland-protocols: src/wayland/protocols/wlr-layer-shell-unstable-v1.xml
mkdir -p src/wayland/protocols
wayland-scanner private-code ${DATA_DIR_WAYLAND_PROTOCOLS}/stable/xdg-shell/xdg-shell.xml src/wayland/protocols/xdg-shell.h
wayland-scanner client-header ${DATA_DIR_WAYLAND_PROTOCOLS}/stable/xdg-shell/xdg-shell.xml src/wayland/protocols/xdg-shell-client-header.h
@ -159,8 +158,6 @@ wayland-protocols: src/wayland/protocols/wlr-layer-shell-unstable-v1.xml src/way
wayland-scanner private-code src/wayland/protocols/wlr-layer-shell-unstable-v1.xml src/wayland/protocols/wlr-layer-shell-unstable-v1.h
wayland-scanner client-header src/wayland/protocols/idle.xml src/wayland/protocols/idle-client-header.h
wayland-scanner private-code src/wayland/protocols/idle.xml src/wayland/protocols/idle.h
wayland-scanner client-header src/wayland/protocols/wlr-foreign-toplevel-management-unstable-v1.xml src/wayland/protocols/wlr-foreign-toplevel-management-unstable-v1-client-header.h
wayland-scanner private-code src/wayland/protocols/wlr-foreign-toplevel-management-unstable-v1.xml src/wayland/protocols/wlr-foreign-toplevel-management-unstable-v1.h
endif
.PHONY: clean clean-dunst clean-dunstify clean-doc clean-tests clean-coverage clean-coverage-run clean-wayland-protocols
@ -178,7 +175,6 @@ clean-dunstify:
clean-doc:
rm -f docs/dunst.1
rm -f docs/dunst.5
rm -f docs/dunstctl.1
rm -fr docs/internal/html
rm -fr docs/internal/coverage

106
README.md
View File

@ -1,95 +1,34 @@
[![main](https://github.com/dunst-project/dunst/workflows/main/badge.svg)](https://github.com/dunst-project/dunst/actions?query=workflow%3Amain) [![codecov](https://codecov.io/gh/dunst-project/dunst/branch/master/graph/badge.svg)](https://codecov.io/gh/dunst-project/dunst)
# Dunst
## Dunst
<i>A highly configurable and lightweight notification daemon.</i>
![music](contrib/screenshots/music.png)
## Table of Contents
* [Features](#features)
* [Building](#building)
* [Documentation](#documentation)
* [Wiki][wiki]
* [Description](#description)
* [Compiling](#compiling)
* [Copyright](#copyright)
# Features
## Description
## ⚙️ Highly customizable
Dunst is a highly configurable and lightweight notification daemon.
Customize fonts, icons, timeouts, and more. Are you unhappy with the default
shortcuts and colors? No worries, you can change these all with a simple
configuration file tweak.
_click the images to see the dunstrc_
<a href="https://gist.github.com/NNBnh/5f6e601a6a82a6ed43b1959698758141">
<img alt="screenshot1" src="contrib/screenshots/screenshot1_cut.png">
</a>
<a href="https://gist.github.com/fwSmit/9127d988b07bcec9d869f2c927d0f616">
<img alt="screenshot2" src="contrib/screenshots/screenshot2_cut.png">
</a>
## 📜 Scripting
<a href="https://gitlab.manjaro.org/profiles-and-settings/manjaro-theme-settings/-/blob/master/skel/.config/dunst/dunstrc">
<img alt="screenshot_urgency" src="contrib/screenshots/screenshot_urgency.png">
</a>
Run custom scripts on notifications matching a specified pattern. Have espeak
read out your notifications, or play a song when your significant other signs on
in pidgin!
## 📋 Rules
Change the look or behavior of notifications matching a specified pattern. You
could use this to change the color of message notifications from your favorite
jabber buddies, or to prevent important work email notifications from
disappearing until you manually dismiss them.
## ⏸️ Pause
If you want to take a break and not receive any notifications for a while, just
pause dunst. All notifications will be saved for you to catch up
later.
## 🕘 History
Catch an unread notification disappearing from the corner of your eye? Just tap
a keyboard shortcut to replay the last notification, or continue tapping to see
your notification history.
# Documentation
Most documentation can be found in dunst's man pages. In
[**dunst(1)**](docs/dunst.1.pod) contains some general instructions on how
to run dunst and in
[**dunst(5)**](docs/dunst.5.pod) all of dunst's configuration options are
explained.
On the dunst [wiki][wiki] you can find guides and installation instructions and
on the dunst [website][website] there is a [FAQ][FAQ] with common issues.
## Installation
Dunst is available in many package repositories. If it's not available in your
distro's repositories, don't worry, it's not hard to build it yourself.
### Dependencies
- dbus (runtime)
Dunst has a number of build dependencies that must be present before attempting configuration. The names are different depending on [distribution](https://github.com/dunst-project/dunst/wiki/Dependencies):
- dbus
- libxinerama
- libxrandr
- libxss
- glib
- pango/cairo
- libnotify (optional, for dunstify)
- libgtk-3-dev
- libnotify (for dunstify only)
- wayland-client (can build without, see [make parameters](#make-parameters))
- wayland-protocols (optional, for recompiling protocols)
The names will be different depending on your [distribution](https://github.com/dunst-project/dunst/wiki/Dependencies).
### Building
```
@ -110,23 +49,14 @@ sudo make install
- `WAYLAND=(0|1)`: Disable/Enable wayland support. (Default: 1 (enabled))
- `SERVICEDIR_SYSTEMD=<PATH>`: The path to put the systemd user service file. Unused, if `SYSTEMD=0`. (Default: detected via `pkg-config`)
- `SERVICEDIR_DBUS=<PATH>`: The path to put the dbus service file. (Default: detected via `pkg-config`)
- `EXTRA_CFLAGS=<FLAGS>`: Additional flags for the compiler.
**Make sure to run all make calls with the same parameter set. So when building with `make PREFIX=/usr`, you have to install it with `make PREFIX=/usr install`, too.**
Checkout the [wiki][wiki] for more information.
## Bug reports
Please use the [issue tracker][issue-tracker] provided by GitHub to send us bug reports or feature requests.
## Screenshots
<a href="https://gist.github.com/MCotocel/2b34486ae59ccda4319fcb93454d212c">
<img alt="screenshot3" src="contrib/screenshots/screenshot3_cut.png">
</a>
<a href="https://gitlab.manjaro.org/profiles-and-settings/manjaro-theme-settings/-/blob/master/skel/.config/dunst/dunstrc">
<img alt="progress" src="https://user-images.githubusercontent.com/23078054/102542111-98b01e00-40b1-11eb-967e-bc952430bd06.png">
</a>
Please use the [issue tracker][issue-tracker] provided by GitHub to send us bug reports or feature requests. You can also join us on the IRC channel `#dunst` on Freenode.
## Maintainers
@ -135,13 +65,13 @@ Please use the [issue tracker][issue-tracker] provided by GitHub to send us bug
## Author
Written by Sascha Kruse <dunst@knopwob.de>
written by Sascha Kruse <dunst@knopwob.de>
## Copyright
Copyright 2013 Sascha Kruse and contributors (see [`LICENSE`](./LICENSE) for licensing information)
copyright 2013 Sascha Kruse and contributors (see [`LICENSE`](./LICENSE) for licensing information)
If you feel that copyrights are violated, please send me an email.
[issue-tracker]: https://github.com/dunst-project/dunst/issues
[wiki]: https://github.com/dunst-project/dunst/wiki
[website]: https://dunst-project.org
[FAQ]: https://dunst-project.org/faq

View File

@ -6,7 +6,6 @@ DATADIR ?= ${PREFIX}/share
# around for backwards compatibility
MANPREFIX ?= ${DATADIR}/man
MANDIR ?= ${MANPREFIX}
EXTRA_CFLAGS ?=
DOXYGEN ?= doxygen
FIND ?= find
@ -37,7 +36,7 @@ endif
# flags
DEFAULT_CPPFLAGS = -D_DEFAULT_SOURCE -DVERSION=\"${VERSION}\"
DEFAULT_CFLAGS = -g --std=gnu99 -pedantic -Wall -Wno-overlength-strings -Os ${STATIC} ${ENABLE_WAYLAND} ${EXTRA_CFLAGS}
DEFAULT_CFLAGS = -g --std=gnu99 -pedantic -Wall -Wno-overlength-strings -Os ${STATIC} ${ENABLE_WAYLAND}
DEFAULT_LDFLAGS = -lm -lrt
CPPFLAGS_DEBUG := -DDEBUG_BUILD

Binary file not shown.

Before

Width:  |  Height:  |  Size: 388 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 672 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 KiB

View File

@ -10,15 +10,6 @@ dunst [-conf file] [-font font] [-geometry geom] [-format fmt] [-follow mode] [-
Dunst is a highly configurable and lightweight notification daemon.
=head2 Autostarting dunst
On most installations dunst should be able to automatically be started by D-Bus
when a notification is sent. This is not recommended when multiple notification
deamons are installed, because D-Bus will not know which one to start.
Other ways of autostarting dunst include starting dunst with your desktop
environment or window manager's autostart functionality or via the provided
systemd service.
=head1 COMMAND LINE OPTIONS
=over 4
@ -169,4 +160,4 @@ If you feel that copyrights are violated, please send me an email.
=head1 SEE ALSO
dunst(5), dunstctl(1), dmenu(1), notify-send(1)
dunst(5), dunstctl(1), dwm(1), dmenu(1), twmn(1), notify-send(1)

View File

@ -249,6 +249,9 @@ Place dunst notifications on the selected layer. Using overlay
will cause notifications to be displayed above fullscreen windows, though
this may also occur at top depending on your compositor.
In Wayland, Notifications won't be delayed when in fullscreen (like when
setting B<fullscreen> to pushback in X11). This is a Wayland limitation.
The bottom layer is below all windows and above the background.
Default: overlay
@ -511,10 +514,9 @@ single notification.
To avoid the corners clipping the icon or text the corner radius will be
automatically lowered to half of the notification height if it exceeds it.
=item B<mouse_left/middle/right_click> (values: [none/do_action/close_current/close_all/context/context_all])
=item B<mouse_left/middle/right_click> (values: [none/do_action/close_current/close_all])
Defines action of mouse click. A touch input in Wayland acts as a mouse left
click.
Defines action of mouse click.
=over 4
@ -524,13 +526,7 @@ Don't do anything.
=item B<do_action> (default for mouse_middle_click)
Invoke the action determined by the action_name rule. If there is no such
action, open the context menu.
=item B<open_url>
If the notification has exactly one url, open it. If there are multiple
ones, open the context menu.
If the notification has exactly one action, or one is marked as default, invoke it. If there are multiple and no default, open the context menu.
=item B<close_current> (default for mouse_left_click)
@ -540,14 +536,6 @@ Close current notification.
Close all notifications.
=item B<context>
Open context menu for the notification.
=item B<context_all>
Open context menu for all notifications.
=back
@ -659,7 +647,7 @@ but also has a lot of extra functionality. So see more see dunstctl(1).
=head1 HISTORY
Dunst saves a number of notifications (specified by B<history_length>) in memory.
These notifications can be recalled (i.e. redisplayed) by calling
These notifications can be recalled (i.e. redisplayed) by calling
B<dunstctl history> (see dunstctl(1)). Whether these notifications will time out
like if they have been just send depends on the value of the B<sticky_history>
setting.
@ -674,15 +662,9 @@ Dunst has Wayland support since version 1.6.0. Because the Wayland protocol
is more focused on security, some things that are possible in X11 are not
possible in Wayland. Those differences are reflected in the configuration.
The main things that change are that dunst on Wayland cannot use global
hotkeys (they are deprecated anyways, use dunstctl).
Some dunst features on wayland might need your compositor to support a certain
protocol. Dunst will warn you if an optional feature isn't supported and will
disable the corresponding functionality.
Fullscreen detection works on wayland with some limitations (see B<fullscreen>).
If you want notifications to appear over fullscreen windows, set
B<layer = overlay> in the global options.
hotkeys (they are deprecated anyways, use dunstctl) and it cannot detect
if an application is fullscreen. If you want to see notifications when in
fullscreen, set B<layer = overlay> in the global options.
Note that the same limitations exist when using xwayland.
If something doesn't quite work in Wayland, please file a bug report. In the
@ -809,7 +791,7 @@ Equivalent to the C<format> setting.
The frame color color of the notification. See COLORS for possible values.
=item C<fullscreen>
=item C<fullscreen> (X11 only)
One of show, delay, or pushback.
@ -824,13 +806,7 @@ Or pushback which is equivalent to delay with the difference that already
existing notifications are paused and hidden until the focus to the fullscreen
window is lost.
On wayland, if B<follow> is set to mouse or keyboard, the output where the
notification is located cannot be determined. So dunst will delay or pushback if
any of the outputs is fullscreen. Since the fullscreen protocol is fairly new,
you will need a recent version of a compositor that supports it. At the time of
writing, you will need the git version of sway.
See also B<layer> to change if notifications appear above fullscreen windows in
Wayland.
See B<layer> to change fullscreen behavior in Wayland
Default: show
@ -874,13 +850,6 @@ later. Use C<msg_urgency> to match it.
Setting this to true will prevent the notification from being displayed
initially but will be saved in history for later viewing.
=item C<action_name>
Sets the name of the action to be invoked on do_action. If not specified, the
action set as default action or the only available action will be invoked.
Default: "default"
=back
As with the filtering attributes, each one corresponds to
@ -941,46 +910,6 @@ dunst is able to get different colors for a message via notify-send.
In order to do that you have to add a hint via the -h option.
The progress value can be set with a hint, too.
B<All hints>
See RULES for more detailed explanations for some options.
=over 4
=item B<fgcolor>:
Foreground cololor
=item B<bgcolor>:
Background color
=item B<frcolor>:
Frame color
=item B<hlcolor>:
Highlight color
=item B<value>:
Progress value.
=item B<image-path>:
Icon name. This may be a path or just the icon name.
=item B<image-data>:
A stream of raw image data.
=item B<category>:
The category.
=item B<desktop_entry>:
The desktop entry.
=item B<transient>:
The transient value.
=back
B<Examples>
=over 4
=item notify-send -h string:fgcolor:#ff4444
@ -1081,4 +1010,4 @@ If you feel that copyrights are violated, please send me an email.
=head1 SEE ALSO
dunst(1), dunstctl(1), dmenu(1), notify-send(1)
dunstctl(1), dwm(1), dmenu(1), twmn(1), notify-send(1)

View File

@ -1,33 +0,0 @@
# Main repo
- [ ] Verify that the changelog is up to date
- [ ] Write release notes (Only if non-patch release)
- [ ] Verify that the working directory is clean and on the master branch
- [ ] Change the version in the Makefile to "x.x.x (iso-date)"
- [ ] Update changelog `Unreleased` entry to the new version
- [ ] Commit changes (Commit title: `Dunst vX.X.X`)
- [ ] Tag commit, make sure it's an annotated tag (git tag -a) (Tag title: Dunst vX.X.X)
- [ ] Push commits
- [ ] Push tags
# Dunst-project.org
- [ ] Update release number in the download page
- [ ] Update release date in the download page
- [ ] Update version number in the download link
- [ ] Copy release notes to the download page (Only if non-patch release)
- [ ] Copy changelog to the changelog page
- [ ] Copy documentation to the documentation page
- [ ] Verify that they look fine when rendered
- [ ] Commit changes
- [ ] Run deploy script
- [ ] Push to main website repo
- [ ] Push to gh-pages
# Main repo
- [ ] Copy release notes to githubs release feature
- [ ] Publish release on github
- [ ] Update maint branch to point to master
- [ ] Create new Unreleased section for the changelog
- [ ] Update Makefile version to -non-git
- [ ] Commit & push

View File

@ -277,14 +277,10 @@
# Defines list of actions for each mouse event
# Possible values are:
# * none: Don't do anything.
# * do_action: Invoke the action determined by the action_name rule. If there is no
# such action, open the context menu.
# * open_url: If the notification has exactly one url, open it. If there are multiple
# ones, open the context menu.
# * do_action: If the notification has exactly one action, or one is marked as default,
# invoke it. If there are multiple and no default, open the context menu.
# * close_current: Close current notification.
# * close_all: Close all notifications.
# * context: Open context menu for the notification.
# * context_all: Open context menu for all notifications.
# These values can be strung together for each mouse event, and
# will be executed in sequence.
mouse_left_click = close_current
@ -377,7 +373,6 @@
# set_transient
# timeout
# urgency
# action_name
#
# Shell-like globbing will get expanded.
#

View File

@ -307,7 +307,6 @@ static void dbus_cb_GetCapabilities(
g_variant_builder_add(builder, "s", "actions");
g_variant_builder_add(builder, "s", "body");
g_variant_builder_add(builder, "s", "body-hyperlinks");
g_variant_builder_add(builder, "s", "icon-static");
for (int i = 0; i < sizeof(stack_tag_hints)/sizeof(*stack_tag_hints); ++i)
g_variant_builder_add(builder, "s", stack_tag_hints[i]);
@ -386,11 +385,6 @@ static struct notification *dbus_message_to_notification(const gchar *sender, GV
g_variant_unref(dict_value);
}
if ((dict_value = g_variant_lookup_value(hints, "hlcolor", G_VARIANT_TYPE_STRING))) {
n->colors.highlight = g_variant_dup_string(dict_value, NULL);
g_variant_unref(dict_value);
}
if ((dict_value = g_variant_lookup_value(hints, "category", G_VARIANT_TYPE_STRING))) {
n->category = g_variant_dup_string(dict_value, NULL);
g_variant_unref(dict_value);

View File

@ -51,6 +51,7 @@ void draw_setup(void)
const struct output *out = output_create(settings.force_xwayland);
output = out;
out->init();
win = out->win_create();
pango_fdesc = pango_font_description_from_string(settings.font);
@ -141,11 +142,10 @@ static struct color layout_get_sepcolor(struct colored_layout *cl,
static void layout_setup_pango(PangoLayout *layout, int width)
{
int scale = output->get_scale();
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
pango_layout_set_width(layout, width * scale * PANGO_SCALE);
pango_layout_set_width(layout, width * PANGO_SCALE);
pango_layout_set_font_description(layout, pango_fdesc);
pango_layout_set_spacing(layout, settings.line_height * scale * PANGO_SCALE);
pango_layout_set_spacing(layout, settings.line_height * PANGO_SCALE);
PangoAlignment align;
switch (settings.align) {
@ -193,20 +193,9 @@ static bool have_progress_bar(const struct notification *n)
return (n->progress >= 0 && settings.progress_bar == true);
}
static void get_text_size(PangoLayout *l, int *w, int *h, int scale) {
pango_layout_get_pixel_size(l, w, h);
// scale the size down, because it may be rendered at higher DPI
if (w)
*w /= scale;
if (h)
*h /= scale;
}
static struct dimensions calculate_dimensions(GSList *layouts)
{
struct dimensions dim = { 0 };
int scale = output->get_scale();
const struct screen_info *scr = output->get_active_screen();
if (have_dynamic_width()) {
@ -233,10 +222,10 @@ static struct dimensions calculate_dimensions(GSList *layouts)
for (GSList *iter = layouts; iter; iter = iter->next) {
struct colored_layout *cl = iter->data;
int w=0,h=0;
get_text_size(cl->l, &w, &h, scale);
pango_layout_get_pixel_size(cl->l, &w, &h);
if (cl->icon) {
h = MAX(get_icon_height(cl->icon, scale), h);
w += get_icon_width(cl->icon, scale) + settings.h_padding;
h = MAX(cairo_image_surface_get_height(cl->icon), h);
w += cairo_image_surface_get_width(cl->icon) + settings.h_padding;
}
h = MAX(settings.notification_height, h + settings.padding * 2);
dim.h += h;
@ -262,15 +251,15 @@ static struct dimensions calculate_dimensions(GSList *layouts)
w -= 2 * settings.h_padding;
w -= 2 * settings.frame_width;
if (cl->icon) {
w -= get_icon_width(cl->icon, scale) + get_text_icon_padding();
w -= cairo_image_surface_get_width(cl->icon) + get_text_icon_padding();
}
layout_setup_pango(cl->l, w);
/* re-read information */
get_text_size(cl->l, &w, &h, scale);
pango_layout_get_pixel_size(cl->l, &w, &h);
if (cl->icon) {
h = MAX(get_icon_height(cl->icon, scale), h);
w += get_icon_width(cl->icon, scale) + settings.h_padding;
h = MAX(cairo_image_surface_get_height(cl->icon), h);
w += cairo_image_surface_get_width(cl->icon) + settings.h_padding;
}
h = MAX(settings.notification_height, h + settings.padding * 2);
dim.h += h;
@ -311,7 +300,6 @@ static struct colored_layout *layout_init_shared(cairo_t *c, const struct notifi
{
struct colored_layout *cl = g_malloc(sizeof(struct colored_layout));
cl->l = layout_create(c);
int scale = output->get_scale();
if (!settings.word_wrap) {
PangoEllipsizeMode ellipsize;
@ -359,7 +347,7 @@ static struct colored_layout *layout_init_shared(cairo_t *c, const struct notifi
width -= 2 * settings.h_padding;
width -= 2 * settings.frame_width;
if (cl->icon) {
width -= get_icon_width(cl->icon, scale) + get_text_icon_padding();
width -= cairo_image_surface_get_width(cl->icon) + get_text_icon_padding();
}
layout_setup_pango(cl->l, width);
}
@ -380,7 +368,6 @@ static struct colored_layout *layout_from_notification(cairo_t *c, struct notifi
{
struct colored_layout *cl = layout_init_shared(c, n);
int scale = output->get_scale();
/* markup */
GError *err = NULL;
@ -402,8 +389,8 @@ static struct colored_layout *layout_from_notification(cairo_t *c, struct notifi
}
get_text_size(cl->l, NULL, &(n->displayed_height), scale);
if (cl->icon) n->displayed_height = MAX(get_icon_height(cl->icon, scale), n->displayed_height);
pango_layout_get_pixel_size(cl->l, NULL, &(n->displayed_height));
if (cl->icon) n->displayed_height = MAX(cairo_image_surface_get_height(cl->icon), n->displayed_height);
n->displayed_height = n->displayed_height + settings.padding * 2;
@ -449,14 +436,14 @@ static GSList *create_layouts(cairo_t *c)
}
static int layout_get_height(struct colored_layout *cl, int scale)
static int layout_get_height(struct colored_layout *cl)
{
int h;
int h_icon = 0;
int h_progress_bar = 0;
get_text_size(cl->l, NULL, &h, scale);
pango_layout_get_pixel_size(cl->l, NULL, &h);
if (cl->icon)
h_icon = get_icon_height(cl->icon, scale);
h_icon = cairo_image_surface_get_height(cl->icon);
if (have_progress_bar(cl->n)){
h_progress_bar = settings.progress_bar_height + settings.padding;
}
@ -496,14 +483,8 @@ static int frame_internal_radius (int r, int w, int h)
* The top corners will get rounded by `corner_radius`, if `first` is set.
* Respectably the same for `last` with the bottom corners.
*/
void draw_rounded_rect(cairo_t *c, int x, int y, int width, int height, int corner_radius, int scale, bool first, bool last)
void draw_rounded_rect(cairo_t *c, int x, int y, int width, int height, int corner_radius, bool first, bool last)
{
width *= scale;
height *= scale;
x *= scale;
y *= scale;
corner_radius *= scale;
const float degrees = M_PI / 180.0;
cairo_new_sub_path(c);
@ -551,13 +532,6 @@ void draw_rounded_rect(cairo_t *c, int x, int y, int width, int height, int corn
cairo_close_path(c);
}
/**
* A small wrapper around cairo_rectange for drawing a scaled rectangle.
*/
void draw_rect(cairo_t *c, int x, int y, int width, int height, int scale) {
cairo_rectangle(c, x * scale, y * scale, width * scale, height * scale);
}
static cairo_surface_t *render_background(cairo_surface_t *srf,
struct colored_layout *cl,
struct colored_layout *cl_next,
@ -567,8 +541,7 @@ static cairo_surface_t *render_background(cairo_surface_t *srf,
int corner_radius,
bool first,
bool last,
int *ret_width,
int scale)
int *ret_width)
{
int x = 0;
int radius_int = corner_radius;
@ -588,7 +561,7 @@ static cairo_surface_t *render_background(cairo_surface_t *srf,
else
height += settings.separator_height;
draw_rounded_rect(c, x, y, width, height, corner_radius, scale, first, last);
draw_rounded_rect(c, x, y, width, height, corner_radius, first, last);
/* adding frame */
x += settings.frame_width;
@ -606,11 +579,11 @@ static cairo_surface_t *render_background(cairo_surface_t *srf,
radius_int = frame_internal_radius(corner_radius, settings.frame_width, height);
draw_rounded_rect(c, x, y, width, height, radius_int, scale, first, last);
draw_rounded_rect(c, x, y, width, height, radius_int, first, last);
cairo_set_source_rgba(c, cl->frame.r, cl->frame.g, cl->frame.b, cl->frame.a);
cairo_fill(c);
draw_rounded_rect(c, x, y, width, height, radius_int, scale, first, last);
draw_rounded_rect(c, x, y, width, height, radius_int, first, last);
cairo_set_source_rgba(c, cl->bg.r, cl->bg.g, cl->bg.b, cl->bg.a);
cairo_fill(c);
@ -622,7 +595,7 @@ static cairo_surface_t *render_background(cairo_surface_t *srf,
struct color sep_color = layout_get_sepcolor(cl, cl_next);
cairo_set_source_rgba(c, sep_color.r, sep_color.g, sep_color.b, sep_color.a);
draw_rect(c, settings.frame_width, y + height, width, settings.separator_height, scale);
cairo_rectangle(c, settings.frame_width, y + height, width, settings.separator_height);
cairo_fill(c);
}
@ -632,18 +605,18 @@ static cairo_surface_t *render_background(cairo_surface_t *srf,
if (ret_width)
*ret_width = width;
return cairo_surface_create_for_rectangle(srf, x * scale, y * scale, width * scale, height * scale);
return cairo_surface_create_for_rectangle(srf, x, y, width, height);
}
static void render_content(cairo_t *c, struct colored_layout *cl, int width, int scale)
static void render_content(cairo_t *c, struct colored_layout *cl, int width)
{
const int h = layout_get_height(cl, scale);
const int h = layout_get_height(cl);
int h_without_progress_bar = h;
if (have_progress_bar(cl->n)){
h_without_progress_bar -= settings.progress_bar_height + settings.padding;
}
int h_text;
get_text_size(cl->l, NULL, &h_text, scale);
pango_layout_get_pixel_size(cl->l, NULL, &h_text);
int text_x = settings.h_padding,
text_y = settings.padding + h_without_progress_bar / 2 - h_text / 2;
@ -661,10 +634,10 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, int
// icon position
if (settings.icon_position == ICON_LEFT) {
text_x = get_icon_width(cl->icon, scale) + settings.h_padding + get_text_icon_padding();
text_x = cairo_image_surface_get_width(cl->icon) + settings.h_padding + get_text_icon_padding();
} // else ICON_RIGHT
}
cairo_move_to(c, text_x * scale, text_y * scale);
cairo_move_to(c, text_x, text_y);
cairo_set_source_rgba(c, cl->fg.r, cl->fg.g, cl->fg.b, cl->fg.a);
pango_cairo_update_layout(c, cl->l);
@ -673,8 +646,8 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, int
// icon positioning
if (cl->icon) {
unsigned int image_width = get_icon_width(cl->icon, scale),
image_height = get_icon_height(cl->icon, scale),
unsigned int image_width = cairo_image_surface_get_width(cl->icon),
image_height = cairo_image_surface_get_height(cl->icon),
image_x = width - settings.h_padding - image_width,
image_y = settings.padding + h_without_progress_bar/2 - image_height/2;
@ -692,8 +665,8 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, int
image_x = settings.h_padding;
} // else ICON_RIGHT
cairo_set_source_surface(c, cl->icon, image_x * scale, image_y * scale);
draw_rect(c, image_x, image_y, image_width, image_height, scale);
cairo_set_source_surface(c, cl->icon, image_x, image_y);
cairo_rectangle(c, image_x, image_y, image_width, image_height);
cairo_fill(c);
}
@ -717,17 +690,16 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, int
// Note: the bar could be drawn a bit smaller, because the frame is drawn on top
// left side
cairo_set_source_rgba(c, cl->highlight.r, cl->highlight.g, cl->highlight.b, cl->highlight.a);
draw_rect(c, x_bar_1, frame_y, progress_width_1, progress_height, scale);
cairo_rectangle(c, x_bar_1, frame_y, progress_width_1, progress_height);
cairo_fill(c);
// right side
cairo_set_source_rgba(c, cl->bg.r, cl->bg.g, cl->bg.b, cl->bg.a);
draw_rect(c, x_bar_2, frame_y, progress_width_2, progress_height, scale);
cairo_rectangle(c, x_bar_2, frame_y, progress_width_2, progress_height);
cairo_fill(c);
// border
cairo_set_source_rgba(c, cl->frame.r, cl->frame.g, cl->frame.b, cl->frame.a);
// TODO draw_rect instead of cairo_rectangle resulted in blurry lines. Why?
cairo_rectangle(c, (frame_x + half_frame_width) * scale, (frame_y + half_frame_width) * scale, (progress_width - frame_width) * scale, progress_height * scale);
cairo_set_line_width(c, frame_width * scale);
cairo_rectangle(c, frame_x + half_frame_width, frame_y + half_frame_width, progress_width - frame_width, progress_height);
cairo_set_line_width(c, frame_width);
cairo_stroke(c);
}
}
@ -739,19 +711,18 @@ static struct dimensions layout_render(cairo_surface_t *srf,
bool first,
bool last)
{
int scale = output->get_scale();
const int cl_h = layout_get_height(cl, scale);
const int cl_h = layout_get_height(cl);
int h_text = 0;
get_text_size(cl->l, NULL, &h_text, scale);
pango_layout_get_pixel_size(cl->l, NULL, &h_text);
int bg_width = 0;
int bg_height = MAX(settings.notification_height, (2 * settings.padding) + cl_h);
cairo_surface_t *content = render_background(srf, cl, cl_next, dim.y, dim.w, bg_height, dim.corner_radius, first, last, &bg_width, scale);
cairo_surface_t *content = render_background(srf, cl, cl_next, dim.y, dim.w, bg_height, dim.corner_radius, first, last, &bg_width);
cairo_t *c = cairo_create(content);
render_content(c, cl, bg_width, scale);
render_content(c, cl, bg_width);
/* adding frame */
if (first)
@ -803,9 +774,8 @@ void draw(void)
GSList *layouts = create_layouts(output->win_get_context(win));
struct dimensions dim = calculate_dimensions(layouts);
int scale = output->get_scale();
cairo_surface_t *image_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, dim.w * scale, dim.h * scale);
cairo_surface_t *image_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, dim.w, dim.h);
bool first = true;
for (GSList *iter = layouts; iter; iter = iter->next) {
@ -830,14 +800,4 @@ void draw_deinit(void)
output->win_destroy(win);
output->deinit();
}
int draw_get_scale(void)
{
if (output) {
return output->get_scale();
} else {
LOG_W("Called draw_get_scale before output init");
return 1;
}
}
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */

View File

@ -12,13 +12,9 @@ void draw_setup(void);
void draw(void);
void draw_rounded_rect(cairo_t *c, int x, int y, int width, int height, int corner_radius, int scale, bool first, bool last);
// TODO get rid of this function by passing scale to everything that needs it.
int draw_get_scale(void);
void draw_rounded_rect(cairo_t *c, int x, int y, int width, int height, int corner_radius, bool first, bool last);
void draw_deinit(void);
#endif
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */

View File

@ -24,7 +24,6 @@
GMainLoop *mainloop = NULL;
static struct dunst_status status;
static bool setup_done = false;
/* see dunst.h */
void dunst_status(const enum dunst_status_field field,
@ -57,14 +56,6 @@ static gboolean run(void *data);
void wake_up(void)
{
// If wake_up is being called before the output has been setup we should
// return.
if (!setup_done)
{
LOG_D("Ignoring wake up");
return;
}
LOG_D("Waking up");
run(NULL);
}
@ -206,7 +197,6 @@ int dunst_main(int argc, char *argv[])
// we do not call wakeup now, wake_up does not work here yet
}
setup_done = true;
run(NULL);
g_main_loop_run(mainloop);
g_clear_pointer(&mainloop, g_main_loop_unref);

View File

@ -86,14 +86,6 @@ static void pixbuf_data_to_cairo_data(
}
}
int get_icon_width(cairo_surface_t *icon, int scale) {
return cairo_image_surface_get_width(icon) / scale;
}
int get_icon_height(cairo_surface_t *icon, int scale) {
return cairo_image_surface_get_height(icon) / scale;
}
cairo_surface_t *gdk_pixbuf_to_cairo_surface(GdkPixbuf *pixbuf)
{
assert(pixbuf);
@ -152,26 +144,22 @@ static bool icon_size_clamp(int *w, int *h) {
*
* @param pixbuf (nullable) The pixbuf, which may be too big.
* Takes ownership of the reference.
* @param dpi_scale An integer for the dpi scaling. That doesn't mean the icon
* is always scaled by dpi_scale.
* @return the scaled version of the pixbuf. If scaling wasn't
* necessary, it returns the same pixbuf. Transfers full
* ownership of the reference.
*/
static GdkPixbuf *icon_pixbuf_scale(GdkPixbuf *pixbuf, int dpi_scale)
static GdkPixbuf *icon_pixbuf_scale(GdkPixbuf *pixbuf)
{
ASSERT_OR_RET(pixbuf, NULL);
int w = gdk_pixbuf_get_width(pixbuf);
int h = gdk_pixbuf_get_height(pixbuf);
// TODO immediately rescale icon upon scale changes
if (icon_size_clamp(&w, &h)) {
GdkPixbuf *scaled = gdk_pixbuf_scale_simple(
pixbuf,
w * dpi_scale,
h * dpi_scale,
w,
h,
GDK_INTERP_BILINEAR);
g_object_unref(pixbuf);
pixbuf = scaled;
@ -180,7 +168,7 @@ static GdkPixbuf *icon_pixbuf_scale(GdkPixbuf *pixbuf, int dpi_scale)
return pixbuf;
}
GdkPixbuf *get_pixbuf_from_file(const char *filename, int scale)
GdkPixbuf *get_pixbuf_from_file(const char *filename)
{
char *path = string_to_path(g_strdup(filename));
GError *error = NULL;
@ -191,11 +179,10 @@ GdkPixbuf *get_pixbuf_from_file(const char *filename, int scale)
g_free(path);
return NULL;
}
// TODO immediately rescale icon upon scale changes
icon_size_clamp(&w, &h);
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_scale(path,
w * scale,
h * scale,
w,
h,
TRUE,
&error);
@ -263,7 +250,7 @@ char *get_path_from_icon_name(const char *iconname)
return new_name;
}
GdkPixbuf *get_pixbuf_from_icon(const char *iconname, int scale)
GdkPixbuf *get_pixbuf_from_icon(const char *iconname)
{
char *path = get_path_from_icon_name(iconname);
if (!path) {
@ -272,7 +259,7 @@ GdkPixbuf *get_pixbuf_from_icon(const char *iconname, int scale)
GdkPixbuf *pixbuf = NULL;
pixbuf = get_pixbuf_from_file(path, scale);
pixbuf = get_pixbuf_from_file(path);
g_free(path);
if (!pixbuf)
@ -281,18 +268,18 @@ GdkPixbuf *get_pixbuf_from_icon(const char *iconname, int scale)
return pixbuf;
}
GdkPixbuf *icon_get_for_name(const char *name, char **id, int scale)
GdkPixbuf *icon_get_for_name(const char *name, char **id)
{
ASSERT_OR_RET(name, NULL);
ASSERT_OR_RET(id, NULL);
GdkPixbuf *pb = get_pixbuf_from_icon(name, scale);
GdkPixbuf *pb = get_pixbuf_from_icon(name);
if (pb)
*id = g_strdup(name);
return pb;
}
GdkPixbuf *icon_get_for_data(GVariant *data, char **id, int dpi_scale)
GdkPixbuf *icon_get_for_data(GVariant *data, char **id)
{
ASSERT_OR_RET(data, NULL);
ASSERT_OR_RET(id, NULL);
@ -360,13 +347,7 @@ GdkPixbuf *icon_get_for_data(GVariant *data, char **id, int dpi_scale)
return NULL;
}
// g_memdup is deprecated in glib 2.67.4 and higher.
// g_memdup2 is a safer alternative
#if GLIB_CHECK_VERSION(2,67,3)
data_pb = (guchar *) g_memdup2(g_variant_get_data(data_variant), len_actual);
#else
data_pb = (guchar *) g_memdup(g_variant_get_data(data_variant), len_actual);
#endif
pixbuf = gdk_pixbuf_new_from_data(data_pb,
GDK_COLORSPACE_RGB,
@ -402,7 +383,7 @@ GdkPixbuf *icon_get_for_data(GVariant *data, char **id, int dpi_scale)
g_free(data_chk);
g_variant_unref(data_variant);
pixbuf = icon_pixbuf_scale(pixbuf, dpi_scale);
pixbuf = icon_pixbuf_scale(pixbuf);
return pixbuf;
}

View File

@ -11,26 +11,11 @@ cairo_surface_t *gdk_pixbuf_to_cairo_surface(GdkPixbuf *pixbuf);
/** Retrieve an icon by its full filepath, scaled according to settings.
*
* @param filename A string representing a readable file path
* @param scale An integer representing the output dpi scaling.
*
* @return an instance of `GdkPixbuf`
* @retval NULL: file does not exist, not readable, etc..
*/
GdkPixbuf *get_pixbuf_from_file(const char *filename, int scale);
/**
* Get the unscaled icon width.
*
* If scale is 2 for example, the icon will render in twice the size, but
* get_icon_width still returns the same size as when scale is 1.
*/
int get_icon_width(cairo_surface_t *icon, int scale);
/**
* Get the unscaled icon height, see get_icon_width.
*/
int get_icon_height(cairo_surface_t *icon, int scale);
GdkPixbuf *get_pixbuf_from_file(const char *filename);
/** Retrieve a path from an icon name.
*
@ -48,12 +33,11 @@ char *get_path_from_icon_name(const char *iconname);
* @param iconname A string describing a `file://` URL, an arbitary filename
* or an icon name, which then gets searched for in the
* settings.icon_path
* @param scale An integer representing the output dpi scaling.
*
* @return an instance of `GdkPixbuf`
* @retval NULL: file does not exist, not readable, etc..
*/
GdkPixbuf *get_pixbuf_from_icon(const char *iconname, int scale);
GdkPixbuf *get_pixbuf_from_icon(const char *iconname);
/** Read an icon from disk and convert it to a GdkPixbuf, scaled according to settings
*
@ -65,11 +49,10 @@ GdkPixbuf *get_pixbuf_from_icon(const char *iconname, int scale);
* get searched in the folders of the icon_path setting.
* @param id (necessary) A unique identifier of the returned pixbuf. Only filled,
* if the return value is non-NULL.
* @param dpi_scale An integer representing the output dpi scaling.
* @return an instance of `GdkPixbuf`, representing the name's image
* @retval NULL: Invalid path given
*/
GdkPixbuf *icon_get_for_name(const char *name, char **id, int dpi_scale);
GdkPixbuf *icon_get_for_name(const char *name, char **id);
/** Convert a GVariant like described in GdkPixbuf, scaled according to settings
*
@ -80,11 +63,10 @@ GdkPixbuf *icon_get_for_name(const char *name, char **id, int dpi_scale);
* like described in the notification spec.
* @param id (necessary) A unique identifier of the returned pixbuf.
* Only filled, if the return value is non-NULL.
* @param scale An integer representing the output dpi scaling.
* @return an instance of `GdkPixbuf` derived from the GVariant
* @retval NULL: GVariant parameter nulled, invalid or in wrong format
*/
GdkPixbuf *icon_get_for_data(GVariant *data, char **id, int scale);
GdkPixbuf *icon_get_for_data(GVariant *data, char **id);
#endif
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */

View File

@ -1,6 +1,5 @@
#include "input.h"
#include "log.h"
#include "menu.h"
#include "settings.h"
#include "queues.h"
#include <stddef.h>
@ -26,10 +25,6 @@ void input_handle_click(unsigned int button, bool button_down, int mouse_x, int
case BTN_RIGHT:
acts = settings.mouse_right_click;
break;
case BTN_TOUCH:
// TODO Add separate action for touch
acts = settings.mouse_left_click;
break;
default:
LOG_W("Unsupported mouse button: '%d'", button);
return;
@ -39,15 +34,10 @@ void input_handle_click(unsigned int button, bool button_down, int mouse_x, int
enum mouse_action act = acts[i];
if (act == MOUSE_CLOSE_ALL) {
queues_history_push_all();
break;
return;
}
if (act == MOUSE_CONTEXT_ALL) {
context_menu();
continue;
}
if (act == MOUSE_DO_ACTION || act == MOUSE_CLOSE_CURRENT || act == MOUSE_CONTEXT || act == MOUSE_OPEN_URL) {
if (act == MOUSE_DO_ACTION || act == MOUSE_CLOSE_CURRENT) {
int y = settings.separator_height;
struct notification *n = NULL;
int first = true;
@ -65,12 +55,8 @@ void input_handle_click(unsigned int button, bool button_down, int mouse_x, int
if (n) {
if (act == MOUSE_CLOSE_CURRENT) {
n->marked_for_closure = REASON_USER;
} else if (act == MOUSE_DO_ACTION) {
notification_do_action(n);
} else if (act == MOUSE_OPEN_URL) {
notification_open_url(n);
} else {
notification_open_context_menu(n);
notification_do_action(n);
}
}
}

View File

@ -74,21 +74,19 @@ static void dunst_log_handler(
gpointer testing)
{
if (testing)
log_level = G_LOG_LEVEL_ERROR;
GLogLevelFlags message_level_masked = message_level & G_LOG_LEVEL_MASK;
return;
/* if you want to have a debug build, you want to log anything,
* unconditionally, without specifying debug log level again */
#ifndef DEBUG_BUILD
if (log_level < message_level_masked)
if (log_level < message_level)
return;
#endif
const char *log_level_str =
log_level_to_string(message_level_masked);
log_level_to_string(message_level & G_LOG_LEVEL_MASK);
/* Use stderr for warnings and higher */
if (message_level_masked <= G_LOG_LEVEL_WARNING)
if (message_level <= G_LOG_LEVEL_WARNING)
g_printerr("%s: %s\n", log_level_str, message);
else
g_print("%s: %s\n", log_level_str, message);

View File

@ -312,19 +312,13 @@ static GList *get_actionable_notifications(void)
/* see menu.h */
void context_menu(void)
{
GList *notifications = get_actionable_notifications();
context_menu_for(notifications);
}
/* see menu.h */
void context_menu_for(GList *notifications)
{
if (menu_ctx.locked_notifications) {
LOG_W("Context menu already running, refusing to rerun");
return;
}
GList *notifications = get_actionable_notifications();
menu_ctx.locked_notifications = notifications;
GError *err = NULL;

View File

@ -2,8 +2,6 @@
#ifndef DUNST_MENU_H
#define DUNST_MENU_H
#include <glib.h>
/**
* Extract all urls from the given string.
*
@ -18,15 +16,9 @@ void invoke_action(const char *action);
void regex_teardown(void);
/**
* Open the context menu that lets the user select urls/actions/etc for all displayed notifications.
* Open the context menu that lets the user select urls/actions/etc.
*/
void context_menu(void);
/**
* Open the context menu that lets the user select urls/actions/etc for the specified notifications.
* @param notifications (nullable) List of notifications for which the context menu should be opened
*/
void context_menu_for(GList *notifications);
#endif
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */

View File

@ -23,7 +23,6 @@
#include "rules.h"
#include "settings.h"
#include "utils.h"
#include "draw.h"
static void notification_extract_urls(struct notification *n);
static void notification_format_message(struct notification *n);
@ -193,7 +192,7 @@ const char *notification_urgency_to_string(const enum urgency urgency)
/* see notification.h */
int notification_cmp(const struct notification *a, const struct notification *b)
{
if (settings.sort && a->urgency != b->urgency) {
if (a->urgency != b->urgency) {
return b->urgency - a->urgency;
} else {
return a->id - b->id;
@ -206,6 +205,8 @@ int notification_cmp_data(const void *va, const void *vb, void *data)
struct notification *a = (struct notification *) va;
struct notification *b = (struct notification *) vb;
ASSERT_OR_RET(settings.sort, 1);
return notification_cmp(a, b);
}
@ -287,7 +288,6 @@ void notification_unref(struct notification *n)
g_free(n->desktop_entry);
g_hash_table_unref(n->actions);
g_free(n->default_action_name);
if (n->icon)
g_object_unref(n->icon);
@ -314,7 +314,7 @@ void notification_icon_replace_path(struct notification *n, const char *new_icon
g_clear_object(&n->icon);
g_clear_pointer(&n->icon_id, g_free);
n->icon = icon_get_for_name(new_icon, &n->icon_id, draw_get_scale());
n->icon = icon_get_for_name(new_icon, &n->icon_id);
}
void notification_icon_replace_data(struct notification *n, GVariant *new_icon)
@ -325,7 +325,7 @@ void notification_icon_replace_data(struct notification *n, GVariant *new_icon)
g_clear_object(&n->icon);
g_clear_pointer(&n->icon_id, g_free);
n->icon = icon_get_for_data(new_icon, &n->icon_id, draw_get_scale());
n->icon = icon_get_for_data(new_icon, &n->icon_id);
}
/* see notification.h */
@ -386,7 +386,6 @@ struct notification *notification_create(void)
n->fullscreen = FS_SHOW;
n->actions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
n->default_action_name = g_strdup("default");
n->script_count = 0;
return n;
@ -648,45 +647,29 @@ void notification_update_text_to_render(struct notification *n)
}
/* see notification.h */
void notification_do_action(struct notification *n)
void notification_do_action(const struct notification *n)
{
assert(n->default_action_name);
if (g_hash_table_size(n->actions)) {
if (g_hash_table_contains(n->actions, n->default_action_name)) {
signal_action_invoked(n, n->default_action_name);
if (g_hash_table_contains(n->actions, "default")) {
signal_action_invoked(n, "default");
return;
}
if (strcmp(n->default_action_name, "default") == 0 && g_hash_table_size(n->actions) == 1) {
if (g_hash_table_size(n->actions) == 1) {
GList *keys = g_hash_table_get_keys(n->actions);
signal_action_invoked(n, keys->data);
g_list_free(keys);
return;
}
notification_open_context_menu(n);
context_menu();
} else if (n->urls) {
if (strstr(n->urls, "\n"))
context_menu();
else
open_browser(n->urls);
}
}
/* see notification.h */
void notification_open_url(struct notification *n)
{
if (strstr(n->urls, "\n"))
notification_open_context_menu(n);
else
open_browser(n->urls);
}
/* see notification.h */
void notification_open_context_menu(struct notification *n)
{
GList *notifications = NULL;
notifications = g_list_append(notifications, n);
notification_lock(n);
context_menu_for(notifications);
}
void notification_invalidate_actions(struct notification *n) {
g_hash_table_remove_all(n->actions);
}

View File

@ -61,7 +61,6 @@ struct notification {
int locked; /**< If non-zero the notification is locked **/
GHashTable *actions;
char *default_action_name; /**< The name of the action to be invoked on do_action */
enum markup_mode markup;
const char *format;
@ -196,24 +195,11 @@ void notification_replace_single_field(char **haystack,
void notification_update_text_to_render(struct notification *n);
/**
* If the notification has an action named n->default_action_name or there is only one
* action and n->default_action_name is set to "default", invoke it. If there is no
* such action, open the context menu if threre are other actions. Otherwise, do nothing.
* If the notification has exactly one action, or one is marked as default,
* invoke it. If there are multiple and no default, open the context menu. If
* there are no actions, proceed similarly with urls.
*/
void notification_do_action(struct notification *n);
/**
* If the notification has exactly one url, invoke it. If there are multiple,
* open the context menu. If there are no urls, do nothing.
*/
void notification_open_url(struct notification *n);
/**
* Open the context menu for the notification.
*
* Convenience function that creates the GList and passes it to context_menu_for().
*/
void notification_open_context_menu(struct notification *n);
void notification_do_action(const struct notification *n);
/**
* Remove all client action data from the notification.

View File

@ -137,9 +137,6 @@ bool string_parse_mouse_action(const char *s, enum mouse_action *ret)
STRING_PARSE_RET("do_action", MOUSE_DO_ACTION);
STRING_PARSE_RET("close_current", MOUSE_CLOSE_CURRENT);
STRING_PARSE_RET("close_all", MOUSE_CLOSE_ALL);
STRING_PARSE_RET("context", MOUSE_CONTEXT);
STRING_PARSE_RET("context_all", MOUSE_CONTEXT_ALL);
STRING_PARSE_RET("open_url", MOUSE_OPEN_URL);
return false;
}

View File

@ -8,7 +8,7 @@
#include "wayland/wl.h"
#endif
bool is_running_wayland(void) {
const bool is_running_wayland(void) {
char* wayland_display = getenv("WAYLAND_DISPLAY");
return !(wayland_display == NULL);
}
@ -24,14 +24,13 @@ const struct output output_x11 = {
x_win_hide,
x_display_surface,
x_win_visible,
x_win_get_context,
get_active_screen,
x_is_idle,
have_fullscreen_window,
x_get_scale,
have_fullscreen_window
};
#ifdef ENABLE_WAYLAND
@ -46,51 +45,28 @@ const struct output output_wl = {
wl_win_hide,
wl_display_surface,
wl_win_visible,
wl_win_get_context,
wl_get_active_screen,
wl_is_idle,
wl_have_fullscreen_window,
wl_get_scale,
wl_have_fullscreen_window
};
#endif
const struct output* get_x11_output() {
const struct output* output = &output_x11;
if (output->init()) {
return output;
} else {
LOG_E("Couldn't initialize X11 output. Aborting...");
}
}
#ifdef ENABLE_WAYLAND
const struct output* get_wl_output() {
const struct output* output = &output_wl;
if (output->init()) {
return output;
} else {
LOG_W("Couldn't initialize wayland output. Falling back to X11 output.");
output->deinit();
return get_x11_output();
}
}
#endif
const struct output* output_create(bool force_xwayland)
{
#ifdef ENABLE_WAYLAND
if (!force_xwayland && is_running_wayland()) {
LOG_I("Using Wayland output");
return get_wl_output();
return &output_wl;
} else {
LOG_I("Using X11 output");
return get_x11_output();
return &output_x11;
}
#else
return get_x11_output();
return &output_x11;
#endif
}
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */

View File

@ -27,7 +27,7 @@ struct screen_info {
};
struct output {
bool (*init)(void);
void (*init)(void);
void (*deinit)(void);
window (*win_create)(void);
@ -38,24 +38,18 @@ struct output {
void (*display_surface)(cairo_surface_t *srf, window win, const struct dimensions*);
bool (*win_visible)(window);
cairo_t* (*win_get_context)(window);
const struct screen_info* (*get_active_screen)(void);
bool (*is_idle)(void);
bool (*have_fullscreen_window)(void);
int (*get_scale)(void);
};
/**
* return an initialized output, selecting the correct output type from either
* wayland or X11 according to the settings and environment.
* When the wayland output fails to initilize, it falls back to X11 output.
*/
const struct output* output_create(bool force_xwayland);
bool is_running_wayland(void);
const bool is_running_wayland(void);
#endif
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */

View File

@ -149,7 +149,7 @@ gint64 queues_get_next_datachange(gint64 time);
* Get the notification which has the given id in the displayed and waiting queue or
* NULL if not found
*
* @param id the id searched for.
* @param the id searched for.
*
* @return the `id` notification or NULL
*/

View File

@ -26,10 +26,6 @@ void rule_apply(struct rule *r, struct notification *n)
n->transient = r->set_transient;
if (r->skip_display != -1)
n->skip_display = r->skip_display;
if (r->action_name) {
g_free(n->default_action_name);
n->default_action_name = g_strdup(r->action_name);
}
if (r->markup != MARKUP_NULL)
n->markup = r->markup;
if (r->new_icon)

View File

@ -23,7 +23,6 @@ struct rule {
/* actions */
gint64 timeout;
enum urgency urgency;
char *action_name;
enum markup_mode markup;
int history_ignore;
int match_transient;

View File

@ -862,7 +862,6 @@ void load_settings(char *cmdline_config_path)
g_free(c);
}
r->action_name = ini_get_string(cur_section, "action_name", NULL);
r->urgency = ini_get_urgency(cur_section, "urgency", r->urgency);
r->msg_urgency = ini_get_urgency(cur_section, "msg_urgency", r->msg_urgency);
r->fg = ini_get_string(cur_section, "foreground", r->fg);

View File

@ -18,7 +18,7 @@ enum icon_position { ICON_LEFT, ICON_RIGHT, ICON_OFF };
enum vertical_alignment { VERTICAL_TOP, VERTICAL_CENTER, VERTICAL_BOTTOM };
enum separator_color { SEP_FOREGROUND, SEP_AUTO, SEP_FRAME, SEP_CUSTOM };
enum follow_mode { FOLLOW_NONE, FOLLOW_MOUSE, FOLLOW_KEYBOARD };
enum mouse_action { MOUSE_NONE, MOUSE_DO_ACTION, MOUSE_CLOSE_CURRENT, MOUSE_CLOSE_ALL, MOUSE_CONTEXT, MOUSE_CONTEXT_ALL, MOUSE_OPEN_URL };
enum mouse_action { MOUSE_NONE, MOUSE_DO_ACTION, MOUSE_CLOSE_CURRENT, MOUSE_CLOSE_ALL };
#ifndef ZWLR_LAYER_SHELL_V1_LAYER_ENUM
#define ZWLR_LAYER_SHELL_V1_LAYER_ENUM
// Needed for compiling without wayland dependency

View File

@ -1,611 +0,0 @@
/* Generated by wayland-scanner 1.18.0 */
#ifndef WLR_FOREIGN_TOPLEVEL_MANAGEMENT_UNSTABLE_V1_CLIENT_PROTOCOL_H
#define WLR_FOREIGN_TOPLEVEL_MANAGEMENT_UNSTABLE_V1_CLIENT_PROTOCOL_H
#include <stdint.h>
#include <stddef.h>
#include "wayland-client.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @page page_wlr_foreign_toplevel_management_unstable_v1 The wlr_foreign_toplevel_management_unstable_v1 protocol
* @section page_ifaces_wlr_foreign_toplevel_management_unstable_v1 Interfaces
* - @subpage page_iface_zwlr_foreign_toplevel_manager_v1 - list and control opened apps
* - @subpage page_iface_zwlr_foreign_toplevel_handle_v1 - an opened toplevel
* @section page_copyright_wlr_foreign_toplevel_management_unstable_v1 Copyright
* <pre>
*
* Copyright © 2018 Ilia Bozhinov
*
* Permission to use, copy, modify, distribute, and sell this
* software and its documentation for any purpose is hereby granted
* without fee, provided that the above copyright notice appear in
* all copies and that both that copyright notice and this permission
* notice appear in supporting documentation, and that the name of
* the copyright holders not be used in advertising or publicity
* pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied
* warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
* THIS SOFTWARE.
* </pre>
*/
struct wl_output;
struct wl_seat;
struct wl_surface;
struct zwlr_foreign_toplevel_handle_v1;
struct zwlr_foreign_toplevel_manager_v1;
/**
* @page page_iface_zwlr_foreign_toplevel_manager_v1 zwlr_foreign_toplevel_manager_v1
* @section page_iface_zwlr_foreign_toplevel_manager_v1_desc Description
*
* The purpose of this protocol is to enable the creation of taskbars
* and docks by providing them with a list of opened applications and
* letting them request certain actions on them, like maximizing, etc.
*
* After a client binds the zwlr_foreign_toplevel_manager_v1, each opened
* toplevel window will be sent via the toplevel event
* @section page_iface_zwlr_foreign_toplevel_manager_v1_api API
* See @ref iface_zwlr_foreign_toplevel_manager_v1.
*/
/**
* @defgroup iface_zwlr_foreign_toplevel_manager_v1 The zwlr_foreign_toplevel_manager_v1 interface
*
* The purpose of this protocol is to enable the creation of taskbars
* and docks by providing them with a list of opened applications and
* letting them request certain actions on them, like maximizing, etc.
*
* After a client binds the zwlr_foreign_toplevel_manager_v1, each opened
* toplevel window will be sent via the toplevel event
*/
extern const struct wl_interface zwlr_foreign_toplevel_manager_v1_interface;
/**
* @page page_iface_zwlr_foreign_toplevel_handle_v1 zwlr_foreign_toplevel_handle_v1
* @section page_iface_zwlr_foreign_toplevel_handle_v1_desc Description
*
* A zwlr_foreign_toplevel_handle_v1 object represents an opened toplevel
* window. Each app may have multiple opened toplevels.
*
* Each toplevel has a list of outputs it is visible on, conveyed to the
* client with the output_enter and output_leave events.
* @section page_iface_zwlr_foreign_toplevel_handle_v1_api API
* See @ref iface_zwlr_foreign_toplevel_handle_v1.
*/
/**
* @defgroup iface_zwlr_foreign_toplevel_handle_v1 The zwlr_foreign_toplevel_handle_v1 interface
*
* A zwlr_foreign_toplevel_handle_v1 object represents an opened toplevel
* window. Each app may have multiple opened toplevels.
*
* Each toplevel has a list of outputs it is visible on, conveyed to the
* client with the output_enter and output_leave events.
*/
extern const struct wl_interface zwlr_foreign_toplevel_handle_v1_interface;
/**
* @ingroup iface_zwlr_foreign_toplevel_manager_v1
* @struct zwlr_foreign_toplevel_manager_v1_listener
*/
struct zwlr_foreign_toplevel_manager_v1_listener {
/**
* a toplevel has been created
*
* This event is emitted whenever a new toplevel window is
* created. It is emitted for all toplevels, regardless of the app
* that has created them.
*
* All initial details of the toplevel(title, app_id, states, etc.)
* will be sent immediately after this event via the corresponding
* events in zwlr_foreign_toplevel_handle_v1.
*/
void (*toplevel)(void *data,
struct zwlr_foreign_toplevel_manager_v1 *zwlr_foreign_toplevel_manager_v1,
struct zwlr_foreign_toplevel_handle_v1 *toplevel);
/**
* the compositor has finished with the toplevel manager
*
* This event indicates that the compositor is done sending
* events to the zwlr_foreign_toplevel_manager_v1. The server will
* destroy the object immediately after sending this request, so it
* will become invalid and the client should free any resources
* associated with it.
*/
void (*finished)(void *data,
struct zwlr_foreign_toplevel_manager_v1 *zwlr_foreign_toplevel_manager_v1);
};
/**
* @ingroup iface_zwlr_foreign_toplevel_manager_v1
*/
static inline int
zwlr_foreign_toplevel_manager_v1_add_listener(struct zwlr_foreign_toplevel_manager_v1 *zwlr_foreign_toplevel_manager_v1,
const struct zwlr_foreign_toplevel_manager_v1_listener *listener, void *data)
{
return wl_proxy_add_listener((struct wl_proxy *) zwlr_foreign_toplevel_manager_v1,
(void (**)(void)) listener, data);
}
#define ZWLR_FOREIGN_TOPLEVEL_MANAGER_V1_STOP 0
/**
* @ingroup iface_zwlr_foreign_toplevel_manager_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_MANAGER_V1_TOPLEVEL_SINCE_VERSION 1
/**
* @ingroup iface_zwlr_foreign_toplevel_manager_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_MANAGER_V1_FINISHED_SINCE_VERSION 1
/**
* @ingroup iface_zwlr_foreign_toplevel_manager_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_MANAGER_V1_STOP_SINCE_VERSION 1
/** @ingroup iface_zwlr_foreign_toplevel_manager_v1 */
static inline void
zwlr_foreign_toplevel_manager_v1_set_user_data(struct zwlr_foreign_toplevel_manager_v1 *zwlr_foreign_toplevel_manager_v1, void *user_data)
{
wl_proxy_set_user_data((struct wl_proxy *) zwlr_foreign_toplevel_manager_v1, user_data);
}
/** @ingroup iface_zwlr_foreign_toplevel_manager_v1 */
static inline void *
zwlr_foreign_toplevel_manager_v1_get_user_data(struct zwlr_foreign_toplevel_manager_v1 *zwlr_foreign_toplevel_manager_v1)
{
return wl_proxy_get_user_data((struct wl_proxy *) zwlr_foreign_toplevel_manager_v1);
}
static inline uint32_t
zwlr_foreign_toplevel_manager_v1_get_version(struct zwlr_foreign_toplevel_manager_v1 *zwlr_foreign_toplevel_manager_v1)
{
return wl_proxy_get_version((struct wl_proxy *) zwlr_foreign_toplevel_manager_v1);
}
/** @ingroup iface_zwlr_foreign_toplevel_manager_v1 */
static inline void
zwlr_foreign_toplevel_manager_v1_destroy(struct zwlr_foreign_toplevel_manager_v1 *zwlr_foreign_toplevel_manager_v1)
{
wl_proxy_destroy((struct wl_proxy *) zwlr_foreign_toplevel_manager_v1);
}
/**
* @ingroup iface_zwlr_foreign_toplevel_manager_v1
*
* Indicates the client no longer wishes to receive events for new toplevels.
* However the compositor may emit further toplevel_created events, until
* the finished event is emitted.
*
* The client must not send any more requests after this one.
*/
static inline void
zwlr_foreign_toplevel_manager_v1_stop(struct zwlr_foreign_toplevel_manager_v1 *zwlr_foreign_toplevel_manager_v1)
{
wl_proxy_marshal((struct wl_proxy *) zwlr_foreign_toplevel_manager_v1,
ZWLR_FOREIGN_TOPLEVEL_MANAGER_V1_STOP);
}
#ifndef ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ENUM
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ENUM
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
* types of states on the toplevel
*
* The different states that a toplevel can have. These have the same meaning
* as the states with the same names defined in xdg-toplevel
*/
enum zwlr_foreign_toplevel_handle_v1_state {
/**
* the toplevel is maximized
*/
ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED = 0,
/**
* the toplevel is minimized
*/
ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MINIMIZED = 1,
/**
* the toplevel is active
*/
ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED = 2,
/**
* the toplevel is fullscreen
* @since 2
*/
ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN = 3,
};
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN_SINCE_VERSION 2
#endif /* ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ENUM */
#ifndef ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_ERROR_ENUM
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_ERROR_ENUM
enum zwlr_foreign_toplevel_handle_v1_error {
/**
* the provided rectangle is invalid
*/
ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_ERROR_INVALID_RECTANGLE = 0,
};
#endif /* ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_ERROR_ENUM */
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
* @struct zwlr_foreign_toplevel_handle_v1_listener
*/
struct zwlr_foreign_toplevel_handle_v1_listener {
/**
* title change
*
* This event is emitted whenever the title of the toplevel
* changes.
*/
void (*title)(void *data,
struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1,
const char *title);
/**
* app-id change
*
* This event is emitted whenever the app-id of the toplevel
* changes.
*/
void (*app_id)(void *data,
struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1,
const char *app_id);
/**
* toplevel entered an output
*
* This event is emitted whenever the toplevel becomes visible on
* the given output. A toplevel may be visible on multiple outputs.
*/
void (*output_enter)(void *data,
struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1,
struct wl_output *output);
/**
* toplevel left an output
*
* This event is emitted whenever the toplevel stops being
* visible on the given output. It is guaranteed that an
* entered-output event with the same output has been emitted
* before this event.
*/
void (*output_leave)(void *data,
struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1,
struct wl_output *output);
/**
* the toplevel state changed
*
* This event is emitted immediately after the
* zlw_foreign_toplevel_handle_v1 is created and each time the
* toplevel state changes, either because of a compositor action or
* because of a request in this protocol.
*/
void (*state)(void *data,
struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1,
struct wl_array *state);
/**
* all information about the toplevel has been sent
*
* This event is sent after all changes in the toplevel state
* have been sent.
*
* This allows changes to the zwlr_foreign_toplevel_handle_v1
* properties to be seen as atomic, even if they happen via
* multiple events.
*/
void (*done)(void *data,
struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1);
/**
* this toplevel has been destroyed
*
* This event means the toplevel has been destroyed. It is
* guaranteed there won't be any more events for this
* zwlr_foreign_toplevel_handle_v1. The toplevel itself becomes
* inert so any requests will be ignored except the destroy
* request.
*/
void (*closed)(void *data,
struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1);
/**
* parent change
*
* This event is emitted whenever the parent of the toplevel
* changes.
*
* No event is emitted when the parent handle is destroyed by the
* client.
* @since 3
*/
void (*parent)(void *data,
struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1,
struct zwlr_foreign_toplevel_handle_v1 *parent);
};
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
static inline int
zwlr_foreign_toplevel_handle_v1_add_listener(struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1,
const struct zwlr_foreign_toplevel_handle_v1_listener *listener, void *data)
{
return wl_proxy_add_listener((struct wl_proxy *) zwlr_foreign_toplevel_handle_v1,
(void (**)(void)) listener, data);
}
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_SET_MAXIMIZED 0
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_UNSET_MAXIMIZED 1
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_SET_MINIMIZED 2
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_UNSET_MINIMIZED 3
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_ACTIVATE 4
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_CLOSE 5
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_SET_RECTANGLE 6
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_DESTROY 7
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_SET_FULLSCREEN 8
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_UNSET_FULLSCREEN 9
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_TITLE_SINCE_VERSION 1
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_APP_ID_SINCE_VERSION 1
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_OUTPUT_ENTER_SINCE_VERSION 1
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_OUTPUT_LEAVE_SINCE_VERSION 1
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_SINCE_VERSION 1
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_DONE_SINCE_VERSION 1
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_CLOSED_SINCE_VERSION 1
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_PARENT_SINCE_VERSION 3
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_SET_MAXIMIZED_SINCE_VERSION 1
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_UNSET_MAXIMIZED_SINCE_VERSION 1
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_SET_MINIMIZED_SINCE_VERSION 1
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_UNSET_MINIMIZED_SINCE_VERSION 1
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_ACTIVATE_SINCE_VERSION 1
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_CLOSE_SINCE_VERSION 1
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_SET_RECTANGLE_SINCE_VERSION 1
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_DESTROY_SINCE_VERSION 1
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_SET_FULLSCREEN_SINCE_VERSION 2
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*/
#define ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_UNSET_FULLSCREEN_SINCE_VERSION 2
/** @ingroup iface_zwlr_foreign_toplevel_handle_v1 */
static inline void
zwlr_foreign_toplevel_handle_v1_set_user_data(struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1, void *user_data)
{
wl_proxy_set_user_data((struct wl_proxy *) zwlr_foreign_toplevel_handle_v1, user_data);
}
/** @ingroup iface_zwlr_foreign_toplevel_handle_v1 */
static inline void *
zwlr_foreign_toplevel_handle_v1_get_user_data(struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1)
{
return wl_proxy_get_user_data((struct wl_proxy *) zwlr_foreign_toplevel_handle_v1);
}
static inline uint32_t
zwlr_foreign_toplevel_handle_v1_get_version(struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1)
{
return wl_proxy_get_version((struct wl_proxy *) zwlr_foreign_toplevel_handle_v1);
}
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*
* Requests that the toplevel be maximized. If the maximized state actually
* changes, this will be indicated by the state event.
*/
static inline void
zwlr_foreign_toplevel_handle_v1_set_maximized(struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1)
{
wl_proxy_marshal((struct wl_proxy *) zwlr_foreign_toplevel_handle_v1,
ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_SET_MAXIMIZED);
}
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*
* Requests that the toplevel be unmaximized. If the maximized state actually
* changes, this will be indicated by the state event.
*/
static inline void
zwlr_foreign_toplevel_handle_v1_unset_maximized(struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1)
{
wl_proxy_marshal((struct wl_proxy *) zwlr_foreign_toplevel_handle_v1,
ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_UNSET_MAXIMIZED);
}
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*
* Requests that the toplevel be minimized. If the minimized state actually
* changes, this will be indicated by the state event.
*/
static inline void
zwlr_foreign_toplevel_handle_v1_set_minimized(struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1)
{
wl_proxy_marshal((struct wl_proxy *) zwlr_foreign_toplevel_handle_v1,
ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_SET_MINIMIZED);
}
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*
* Requests that the toplevel be unminimized. If the minimized state actually
* changes, this will be indicated by the state event.
*/
static inline void
zwlr_foreign_toplevel_handle_v1_unset_minimized(struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1)
{
wl_proxy_marshal((struct wl_proxy *) zwlr_foreign_toplevel_handle_v1,
ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_UNSET_MINIMIZED);
}
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*
* Request that this toplevel be activated on the given seat.
* There is no guarantee the toplevel will be actually activated.
*/
static inline void
zwlr_foreign_toplevel_handle_v1_activate(struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1, struct wl_seat *seat)
{
wl_proxy_marshal((struct wl_proxy *) zwlr_foreign_toplevel_handle_v1,
ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_ACTIVATE, seat);
}
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*
* Send a request to the toplevel to close itself. The compositor would
* typically use a shell-specific method to carry out this request, for
* example by sending the xdg_toplevel.close event. However, this gives
* no guarantees the toplevel will actually be destroyed. If and when
* this happens, the zwlr_foreign_toplevel_handle_v1.closed event will
* be emitted.
*/
static inline void
zwlr_foreign_toplevel_handle_v1_close(struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1)
{
wl_proxy_marshal((struct wl_proxy *) zwlr_foreign_toplevel_handle_v1,
ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_CLOSE);
}
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*
* The rectangle of the surface specified in this request corresponds to
* the place where the app using this protocol represents the given toplevel.
* It can be used by the compositor as a hint for some operations, e.g
* minimizing. The client is however not required to set this, in which
* case the compositor is free to decide some default value.
*
* If the client specifies more than one rectangle, only the last one is
* considered.
*
* The dimensions are given in surface-local coordinates.
* Setting width=height=0 removes the already-set rectangle.
*/
static inline void
zwlr_foreign_toplevel_handle_v1_set_rectangle(struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1, struct wl_surface *surface, int32_t x, int32_t y, int32_t width, int32_t height)
{
wl_proxy_marshal((struct wl_proxy *) zwlr_foreign_toplevel_handle_v1,
ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_SET_RECTANGLE, surface, x, y, width, height);
}
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*
* Destroys the zwlr_foreign_toplevel_handle_v1 object.
*
* This request should be called either when the client does not want to
* use the toplevel anymore or after the closed event to finalize the
* destruction of the object.
*/
static inline void
zwlr_foreign_toplevel_handle_v1_destroy(struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1)
{
wl_proxy_marshal((struct wl_proxy *) zwlr_foreign_toplevel_handle_v1,
ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_DESTROY);
wl_proxy_destroy((struct wl_proxy *) zwlr_foreign_toplevel_handle_v1);
}
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*
* Requests that the toplevel be fullscreened on the given output. If the
* fullscreen state and/or the outputs the toplevel is visible on actually
* change, this will be indicated by the state and output_enter/leave
* events.
*
* The output parameter is only a hint to the compositor. Also, if output
* is NULL, the compositor should decide which output the toplevel will be
* fullscreened on, if at all.
*/
static inline void
zwlr_foreign_toplevel_handle_v1_set_fullscreen(struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1, struct wl_output *output)
{
wl_proxy_marshal((struct wl_proxy *) zwlr_foreign_toplevel_handle_v1,
ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_SET_FULLSCREEN, output);
}
/**
* @ingroup iface_zwlr_foreign_toplevel_handle_v1
*
* Requests that the toplevel be unfullscreened. If the fullscreen state
* actually changes, this will be indicated by the state event.
*/
static inline void
zwlr_foreign_toplevel_handle_v1_unset_fullscreen(struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel_handle_v1)
{
wl_proxy_marshal((struct wl_proxy *) zwlr_foreign_toplevel_handle_v1,
ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_UNSET_FULLSCREEN);
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,106 +0,0 @@
/* Generated by wayland-scanner 1.18.0 */
/*
* Copyright © 2018 Ilia Bozhinov
*
* Permission to use, copy, modify, distribute, and sell this
* software and its documentation for any purpose is hereby granted
* without fee, provided that the above copyright notice appear in
* all copies and that both that copyright notice and this permission
* notice appear in supporting documentation, and that the name of
* the copyright holders not be used in advertising or publicity
* pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied
* warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
* THIS SOFTWARE.
*/
#include <stdlib.h>
#include <stdint.h>
#include "wayland-util.h"
#ifndef __has_attribute
# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
#endif
#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
#define WL_PRIVATE __attribute__ ((visibility("hidden")))
#else
#define WL_PRIVATE
#endif
extern const struct wl_interface wl_output_interface;
extern const struct wl_interface wl_seat_interface;
extern const struct wl_interface wl_surface_interface;
extern const struct wl_interface zwlr_foreign_toplevel_handle_v1_interface;
static const struct wl_interface *wlr_foreign_toplevel_management_unstable_v1_types[] = {
NULL,
&zwlr_foreign_toplevel_handle_v1_interface,
&wl_seat_interface,
&wl_surface_interface,
NULL,
NULL,
NULL,
NULL,
&wl_output_interface,
&wl_output_interface,
&wl_output_interface,
&zwlr_foreign_toplevel_handle_v1_interface,
};
static const struct wl_message zwlr_foreign_toplevel_manager_v1_requests[] = {
{ "stop", "", wlr_foreign_toplevel_management_unstable_v1_types + 0 },
};
static const struct wl_message zwlr_foreign_toplevel_manager_v1_events[] = {
{ "toplevel", "n", wlr_foreign_toplevel_management_unstable_v1_types + 1 },
{ "finished", "", wlr_foreign_toplevel_management_unstable_v1_types + 0 },
};
WL_PRIVATE const struct wl_interface zwlr_foreign_toplevel_manager_v1_interface = {
"zwlr_foreign_toplevel_manager_v1", 3,
1, zwlr_foreign_toplevel_manager_v1_requests,
2, zwlr_foreign_toplevel_manager_v1_events,
};
static const struct wl_message zwlr_foreign_toplevel_handle_v1_requests[] = {
{ "set_maximized", "", wlr_foreign_toplevel_management_unstable_v1_types + 0 },
{ "unset_maximized", "", wlr_foreign_toplevel_management_unstable_v1_types + 0 },
{ "set_minimized", "", wlr_foreign_toplevel_management_unstable_v1_types + 0 },
{ "unset_minimized", "", wlr_foreign_toplevel_management_unstable_v1_types + 0 },
{ "activate", "o", wlr_foreign_toplevel_management_unstable_v1_types + 2 },
{ "close", "", wlr_foreign_toplevel_management_unstable_v1_types + 0 },
{ "set_rectangle", "oiiii", wlr_foreign_toplevel_management_unstable_v1_types + 3 },
{ "destroy", "", wlr_foreign_toplevel_management_unstable_v1_types + 0 },
{ "set_fullscreen", "2?o", wlr_foreign_toplevel_management_unstable_v1_types + 8 },
{ "unset_fullscreen", "2", wlr_foreign_toplevel_management_unstable_v1_types + 0 },
};
static const struct wl_message zwlr_foreign_toplevel_handle_v1_events[] = {
{ "title", "s", wlr_foreign_toplevel_management_unstable_v1_types + 0 },
{ "app_id", "s", wlr_foreign_toplevel_management_unstable_v1_types + 0 },
{ "output_enter", "o", wlr_foreign_toplevel_management_unstable_v1_types + 9 },
{ "output_leave", "o", wlr_foreign_toplevel_management_unstable_v1_types + 10 },
{ "state", "a", wlr_foreign_toplevel_management_unstable_v1_types + 0 },
{ "done", "", wlr_foreign_toplevel_management_unstable_v1_types + 0 },
{ "closed", "", wlr_foreign_toplevel_management_unstable_v1_types + 0 },
{ "parent", "3?o", wlr_foreign_toplevel_management_unstable_v1_types + 11 },
};
WL_PRIVATE const struct wl_interface zwlr_foreign_toplevel_handle_v1_interface = {
"zwlr_foreign_toplevel_handle_v1", 3,
10, zwlr_foreign_toplevel_handle_v1_requests,
8, zwlr_foreign_toplevel_handle_v1_events,
};

View File

@ -1,270 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="wlr_foreign_toplevel_management_unstable_v1">
<copyright>
Copyright © 2018 Ilia Bozhinov
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that copyright notice and this permission
notice appear in supporting documentation, and that the name of
the copyright holders not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission. The copyright holders make no
representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied
warranty.
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
</copyright>
<interface name="zwlr_foreign_toplevel_manager_v1" version="3">
<description summary="list and control opened apps">
The purpose of this protocol is to enable the creation of taskbars
and docks by providing them with a list of opened applications and
letting them request certain actions on them, like maximizing, etc.
After a client binds the zwlr_foreign_toplevel_manager_v1, each opened
toplevel window will be sent via the toplevel event
</description>
<event name="toplevel">
<description summary="a toplevel has been created">
This event is emitted whenever a new toplevel window is created. It
is emitted for all toplevels, regardless of the app that has created
them.
All initial details of the toplevel(title, app_id, states, etc.) will
be sent immediately after this event via the corresponding events in
zwlr_foreign_toplevel_handle_v1.
</description>
<arg name="toplevel" type="new_id" interface="zwlr_foreign_toplevel_handle_v1"/>
</event>
<request name="stop">
<description summary="stop sending events">
Indicates the client no longer wishes to receive events for new toplevels.
However the compositor may emit further toplevel_created events, until
the finished event is emitted.
The client must not send any more requests after this one.
</description>
</request>
<event name="finished">
<description summary="the compositor has finished with the toplevel manager">
This event indicates that the compositor is done sending events to the
zwlr_foreign_toplevel_manager_v1. The server will destroy the object
immediately after sending this request, so it will become invalid and
the client should free any resources associated with it.
</description>
</event>
</interface>
<interface name="zwlr_foreign_toplevel_handle_v1" version="3">
<description summary="an opened toplevel">
A zwlr_foreign_toplevel_handle_v1 object represents an opened toplevel
window. Each app may have multiple opened toplevels.
Each toplevel has a list of outputs it is visible on, conveyed to the
client with the output_enter and output_leave events.
</description>
<event name="title">
<description summary="title change">
This event is emitted whenever the title of the toplevel changes.
</description>
<arg name="title" type="string"/>
</event>
<event name="app_id">
<description summary="app-id change">
This event is emitted whenever the app-id of the toplevel changes.
</description>
<arg name="app_id" type="string"/>
</event>
<event name="output_enter">
<description summary="toplevel entered an output">
This event is emitted whenever the toplevel becomes visible on
the given output. A toplevel may be visible on multiple outputs.
</description>
<arg name="output" type="object" interface="wl_output"/>
</event>
<event name="output_leave">
<description summary="toplevel left an output">
This event is emitted whenever the toplevel stops being visible on
the given output. It is guaranteed that an entered-output event
with the same output has been emitted before this event.
</description>
<arg name="output" type="object" interface="wl_output"/>
</event>
<request name="set_maximized">
<description summary="requests that the toplevel be maximized">
Requests that the toplevel be maximized. If the maximized state actually
changes, this will be indicated by the state event.
</description>
</request>
<request name="unset_maximized">
<description summary="requests that the toplevel be unmaximized">
Requests that the toplevel be unmaximized. If the maximized state actually
changes, this will be indicated by the state event.
</description>
</request>
<request name="set_minimized">
<description summary="requests that the toplevel be minimized">
Requests that the toplevel be minimized. If the minimized state actually
changes, this will be indicated by the state event.
</description>
</request>
<request name="unset_minimized">
<description summary="requests that the toplevel be unminimized">
Requests that the toplevel be unminimized. If the minimized state actually
changes, this will be indicated by the state event.
</description>
</request>
<request name="activate">
<description summary="activate the toplevel">
Request that this toplevel be activated on the given seat.
There is no guarantee the toplevel will be actually activated.
</description>
<arg name="seat" type="object" interface="wl_seat"/>
</request>
<enum name="state">
<description summary="types of states on the toplevel">
The different states that a toplevel can have. These have the same meaning
as the states with the same names defined in xdg-toplevel
</description>
<entry name="maximized" value="0" summary="the toplevel is maximized"/>
<entry name="minimized" value="1" summary="the toplevel is minimized"/>
<entry name="activated" value="2" summary="the toplevel is active"/>
<entry name="fullscreen" value="3" summary="the toplevel is fullscreen" since="2"/>
</enum>
<event name="state">
<description summary="the toplevel state changed">
This event is emitted immediately after the zlw_foreign_toplevel_handle_v1
is created and each time the toplevel state changes, either because of a
compositor action or because of a request in this protocol.
</description>
<arg name="state" type="array"/>
</event>
<event name="done">
<description summary="all information about the toplevel has been sent">
This event is sent after all changes in the toplevel state have been
sent.
This allows changes to the zwlr_foreign_toplevel_handle_v1 properties
to be seen as atomic, even if they happen via multiple events.
</description>
</event>
<request name="close">
<description summary="request that the toplevel be closed">
Send a request to the toplevel to close itself. The compositor would
typically use a shell-specific method to carry out this request, for
example by sending the xdg_toplevel.close event. However, this gives
no guarantees the toplevel will actually be destroyed. If and when
this happens, the zwlr_foreign_toplevel_handle_v1.closed event will
be emitted.
</description>
</request>
<request name="set_rectangle">
<description summary="the rectangle which represents the toplevel">
The rectangle of the surface specified in this request corresponds to
the place where the app using this protocol represents the given toplevel.
It can be used by the compositor as a hint for some operations, e.g
minimizing. The client is however not required to set this, in which
case the compositor is free to decide some default value.
If the client specifies more than one rectangle, only the last one is
considered.
The dimensions are given in surface-local coordinates.
Setting width=height=0 removes the already-set rectangle.
</description>
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="x" type="int"/>
<arg name="y" type="int"/>
<arg name="width" type="int"/>
<arg name="height" type="int"/>
</request>
<enum name="error">
<entry name="invalid_rectangle" value="0"
summary="the provided rectangle is invalid"/>
</enum>
<event name="closed">
<description summary="this toplevel has been destroyed">
This event means the toplevel has been destroyed. It is guaranteed there
won't be any more events for this zwlr_foreign_toplevel_handle_v1. The
toplevel itself becomes inert so any requests will be ignored except the
destroy request.
</description>
</event>
<request name="destroy" type="destructor">
<description summary="destroy the zwlr_foreign_toplevel_handle_v1 object">
Destroys the zwlr_foreign_toplevel_handle_v1 object.
This request should be called either when the client does not want to
use the toplevel anymore or after the closed event to finalize the
destruction of the object.
</description>
</request>
<!-- Version 2 additions -->
<request name="set_fullscreen" since="2">
<description summary="request that the toplevel be fullscreened">
Requests that the toplevel be fullscreened on the given output. If the
fullscreen state and/or the outputs the toplevel is visible on actually
change, this will be indicated by the state and output_enter/leave
events.
The output parameter is only a hint to the compositor. Also, if output
is NULL, the compositor should decide which output the toplevel will be
fullscreened on, if at all.
</description>
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
</request>
<request name="unset_fullscreen" since="2">
<description summary="request that the toplevel be unfullscreened">
Requests that the toplevel be unfullscreened. If the fullscreen state
actually changes, this will be indicated by the state event.
</description>
</request>
<!-- Version 3 additions -->
<event name="parent" since="3">
<description summary="parent change">
This event is emitted whenever the parent of the toplevel changes.
No event is emitted when the parent handle is destroyed by the client.
</description>
<arg name="parent" type="object" interface="zwlr_foreign_toplevel_handle_v1" allow-null="true"/>
</event>
</interface>
</protocol>

View File

@ -19,8 +19,6 @@
#include "protocols/xdg-shell.h"
#include "protocols/wlr-layer-shell-unstable-v1-client-header.h"
#include "protocols/wlr-layer-shell-unstable-v1.h"
#include "protocols/wlr-foreign-toplevel-management-unstable-v1-client-header.h"
#include "protocols/wlr-foreign-toplevel-management-unstable-v1.h"
#include "protocols/idle-client-header.h"
#include "protocols/idle.h"
#include "pool-buffer.h"
@ -32,8 +30,6 @@
#include "../input.h"
#include "libgwater-wayland.h"
#define MAX_TOUCHPOINTS 10
struct window_wl {
cairo_surface_t *c_surface;
cairo_t * c_ctx;
@ -58,7 +54,6 @@ struct wl_ctx {
struct wl_callback *frame_callback;
struct org_kde_kwin_idle *idle_handler;
struct org_kde_kwin_idle_timeout *idle_timeout;
struct zwlr_foreign_toplevel_manager_v1 *toplevel_manager;
bool configured;
bool dirty;
bool is_idle;
@ -69,13 +64,6 @@ struct wl_ctx {
int32_t x, y;
} pointer;
struct {
struct wl_touch *wl_touch;
struct {
int32_t x, y;
} pts[MAX_TOUCHPOINTS];
} touch;
struct dimensions cur_dim;
int32_t width, height;
@ -91,10 +79,9 @@ struct dunst_output {
uint32_t scale;
uint32_t subpixel; // TODO do something with it
bool fullscreen;
struct zwlr_foreign_toplevel_handle_v1 *fullscreen_toplevel; // the toplevel that is fullscreened on this output
};
struct wl_ctx ctx;
static void noop() {
@ -107,7 +94,7 @@ static void output_handle_geometry(void *data, struct wl_output *wl_output,
int32_t x, int32_t y, int32_t phy_width, int32_t phy_height,
int32_t subpixel, const char *make, const char *model,
int32_t transform) {
//TODO do something with the subpixel data
//TODO
struct dunst_output *output = data;
output->subpixel = subpixel;
}
@ -116,8 +103,6 @@ static void output_handle_scale(void *data, struct wl_output *wl_output,
int32_t factor) {
struct dunst_output *output = data;
output->scale = factor;
wake_up();
}
static const struct wl_output_listener output_listener = {
@ -137,8 +122,8 @@ static void create_output( struct wl_output *wl_output, uint32_t global_name) {
LOG_I("New output found - id %i", number);
output->global_name = global_name;
output->wl_output = wl_output;
// TODO: Fix this
output->scale = 1;
output->fullscreen = false;
wl_list_insert(&ctx.outputs, &output->link);
wl_output_set_user_data(wl_output, output);
@ -159,36 +144,7 @@ static void destroy_output(struct dunst_output *output) {
free(output);
}
static void touch_handle_motion(void *data, struct wl_touch *wl_touch,
uint32_t time, int32_t id,
wl_fixed_t surface_x, wl_fixed_t surface_y) {
if (id >= MAX_TOUCHPOINTS) {
return;
}
ctx.touch.pts[id].x = wl_fixed_to_int(surface_x);
ctx.touch.pts[id].y = wl_fixed_to_int(surface_y);
}
static void touch_handle_down(void *data, struct wl_touch *wl_touch,
uint32_t serial, uint32_t time, struct wl_surface *sfc, int32_t id,
wl_fixed_t surface_x, wl_fixed_t surface_y) {
if (id >= MAX_TOUCHPOINTS) {
return;
}
ctx.touch.pts[id].x = wl_fixed_to_int(surface_x);
ctx.touch.pts[id].y = wl_fixed_to_int(surface_y);
}
static void touch_handle_up(void *data, struct wl_touch *wl_touch,
uint32_t serial, uint32_t time, int32_t id) {
if (id >= MAX_TOUCHPOINTS) {
return;
}
input_handle_click(BTN_TOUCH, false,
ctx.touch.pts[id].x, ctx.touch.pts[id].y);
}
// FIXME: Snipped touch handling
static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer,
uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) {
ctx.pointer.x = wl_fixed_to_int(surface_x);
@ -209,13 +165,7 @@ static const struct wl_pointer_listener pointer_listener = {
.axis = noop,
};
static const struct wl_touch_listener touch_listener = {
.down = touch_handle_down,
.up = touch_handle_up,
.motion = touch_handle_motion,
.frame = noop,
.cancel = noop,
};
// FIXME snipped touch listener
static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
uint32_t capabilities) {
@ -228,15 +178,7 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
ctx.pointer.wl_pointer = wl_seat_get_pointer(wl_seat);
wl_pointer_add_listener(ctx.pointer.wl_pointer,
&pointer_listener, ctx.seat);
}
if (ctx.touch.wl_touch != NULL) {
wl_touch_release(ctx.touch.wl_touch);
ctx.touch.wl_touch = NULL;
}
if (capabilities & WL_SEAT_CAPABILITY_TOUCH) {
ctx.touch.wl_touch = wl_seat_get_touch(wl_seat);
wl_touch_add_listener(ctx.touch.wl_touch,
&touch_listener, ctx.seat);
LOG_I("Adding pointer");
}
}
@ -284,12 +226,10 @@ static void layer_surface_handle_configure(void *data,
static void layer_surface_handle_closed(void *data,
struct zwlr_layer_surface_v1 *surface) {
LOG_I("Destroying layer");
if (ctx.layer_surface)
zwlr_layer_surface_v1_destroy(ctx.layer_surface);
zwlr_layer_surface_v1_destroy(ctx.layer_surface);
ctx.layer_surface = NULL;
if (ctx.surface)
wl_surface_destroy(ctx.surface);
wl_surface_destroy(ctx.surface);
ctx.surface = NULL;
if (ctx.frame_callback) {
@ -317,11 +257,11 @@ static const struct zwlr_layer_surface_v1_listener layer_surface_listener = {
static void idle_start (void *data, struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout) {
ctx.is_idle = true;
LOG_D("User went idle");
LOG_I("User went idle");
}
static void idle_stop (void *data, struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout) {
ctx.is_idle = false;
LOG_D("User isn't idle anymore");
LOG_I("User isn't idle anymore");
}
static const struct org_kde_kwin_idle_timeout_listener idle_timeout_listener = {
@ -333,183 +273,34 @@ static void add_seat_to_idle_handler(struct wl_seat *seat) {
if (!ctx.idle_handler){
return;
}
if (settings.idle_threshold > 0) {
uint32_t timeout_ms = settings.idle_threshold/1000;
ctx.idle_timeout = org_kde_kwin_idle_get_idle_timeout(ctx.idle_handler, seat, timeout_ms);
org_kde_kwin_idle_timeout_add_listener(ctx.idle_timeout, &idle_timeout_listener, 0);
ctx.has_idle_monitor = true;
}
uint32_t timeout_ms = settings.idle_threshold/1000;
ctx.idle_timeout = org_kde_kwin_idle_get_idle_timeout(ctx.idle_handler, seat, timeout_ms);
org_kde_kwin_idle_timeout_add_listener(ctx.idle_timeout, &idle_timeout_listener, 0);
ctx.has_idle_monitor = true;
}
// Warning, can return NULL
static struct dunst_output *get_configured_output() {
int n = 0;
int target_monitor = settings.monitor;
struct dunst_output *first_output = NULL, *configured_output = NULL,
*tmp_output = NULL;
wl_list_for_each(tmp_output, &ctx.outputs, link) {
if (n == 0)
first_output = tmp_output;
if (n == target_monitor)
configured_output = tmp_output;
n++;
}
// There's only 1 output, so return that
if (n == 1)
return first_output;
switch (settings.f_mode){
case FOLLOW_NONE: ; // this semicolon is neccesary
if (!configured_output) {
LOG_W("Monitor %i doesn't exist, using focused monitor", settings.monitor);
}
return configured_output;
case FOLLOW_MOUSE:
// fallthrough
case FOLLOW_KEYBOARD:
// fallthrough
default:
return NULL;
}
}
// does not do null checking
static void dunst_output_set_fullscreen(struct dunst_output *output,
struct zwlr_foreign_toplevel_handle_v1 *toplevel,
bool fullscreen) {
output->fullscreen = fullscreen;
if (fullscreen)
output->fullscreen_toplevel = toplevel;
else
output->fullscreen_toplevel = NULL;
LOG_D("Set output %i fullscreen state %i", output->global_name, fullscreen);
wake_up();
}
static void toplevel_output_leave(void *data,
struct zwlr_foreign_toplevel_handle_v1 *toplevel,
struct wl_output *output) {
zwlr_foreign_toplevel_handle_v1_set_user_data(toplevel, NULL);
}
static void toplevel_output_enter(void *data,
struct zwlr_foreign_toplevel_handle_v1 *toplevel,
struct wl_output *output) {
// FIXME toplevel can be on multiple outputs, so a list of outputs should be kept
zwlr_foreign_toplevel_handle_v1_set_user_data(toplevel, output);
}
static void toplevel_closed(void *data,
struct zwlr_foreign_toplevel_handle_v1 *toplevel) {
struct wl_output *output_wl = (struct wl_output*) data;
if (output_wl == NULL) {
return;
}
struct dunst_output *output = (struct dunst_output*) wl_output_get_user_data(output_wl);
if (output == NULL) {
return;
}
dunst_output_set_fullscreen(output, toplevel, false);
}
static void toplevel_state(void *data,
struct zwlr_foreign_toplevel_handle_v1 *toplevel,
struct wl_array *state) {
struct wl_output *output_wl = (struct wl_output*) data;
if (output_wl == NULL) {
return;
}
struct dunst_output *output = (struct dunst_output*) wl_output_get_user_data(output_wl);
if (output == NULL) {
return;
}
bool fullscreen = false;
bool activated = false;
enum zwlr_foreign_toplevel_handle_v1_state* element;
wl_array_for_each(element, state){
if (*element == ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN) {
fullscreen = true;
}
if (*element == ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED) {
activated = true;
}
}
if (fullscreen && activated) {
dunst_output_set_fullscreen(output, toplevel, true);
} else {
if (output->fullscreen_toplevel == toplevel) {
// this toplevel was fullscreen, but isn't anymore
dunst_output_set_fullscreen(output, toplevel, false);
}
}
}
static const struct zwlr_foreign_toplevel_handle_v1_listener foreign_toplevel_handle_listener = {
.title = noop,
.app_id = noop,
.output_enter = toplevel_output_enter,
.output_leave = toplevel_output_leave,
.state = toplevel_state,
.done = noop,
.closed = toplevel_closed,
};
static void toplevel_created(void *data,
struct zwlr_foreign_toplevel_manager_v1 *zwlr_foreign_toplevel_manager_v1,
struct zwlr_foreign_toplevel_handle_v1 *toplevel){
zwlr_foreign_toplevel_handle_v1_add_listener(toplevel, &foreign_toplevel_handle_listener, NULL);
}
static void toplevel_finished(void *data,
struct zwlr_foreign_toplevel_manager_v1 *zwlr_foreign_toplevel_manager_v1){
}
static const struct zwlr_foreign_toplevel_manager_v1_listener foreign_toplevel_manager_listener = {
.toplevel = toplevel_created,
.finished = toplevel_finished,
};
static void handle_global(void *data, struct wl_registry *registry,
uint32_t name, const char *interface, uint32_t version) {
int *count = data;
if (*count == 0)
{
if (strcmp(interface, wl_compositor_interface.name) == 0) {
ctx.compositor = wl_registry_bind(registry, name,
&wl_compositor_interface, 4);
} else if (strcmp(interface, wl_shm_interface.name) == 0) {
ctx.shm = wl_registry_bind(registry, name,
&wl_shm_interface, 1);
} else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
ctx.layer_shell = wl_registry_bind(registry, name,
&zwlr_layer_shell_v1_interface, 1);
} else if (strcmp(interface, wl_seat_interface.name) == 0) {
ctx.seat = wl_registry_bind(registry, name, &wl_seat_interface, 3);
wl_seat_add_listener(ctx.seat, &seat_listener, ctx.seat);
add_seat_to_idle_handler(ctx.seat);
} else if (strcmp(interface, wl_output_interface.name) == 0) {
struct wl_output *output =
wl_registry_bind(registry, name, &wl_output_interface, 3);
create_output(output, name);
} else if (strcmp(interface, org_kde_kwin_idle_interface.name) == 0 &&
version >= ORG_KDE_KWIN_IDLE_TIMEOUT_IDLE_SINCE_VERSION) {
ctx.idle_handler = wl_registry_bind(registry, name, &org_kde_kwin_idle_interface, 1);
}
} else {
if (strcmp(interface, zwlr_foreign_toplevel_manager_v1_interface.name) == 0 &&
version >= ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN_SINCE_VERSION) {
// Only bind after the second pass to bind after binding to all the outputs.
// This is because otherwise toplevel_enter evens won't be sent.
ctx.toplevel_manager = wl_registry_bind(registry, name, &zwlr_foreign_toplevel_manager_v1_interface, 2);
zwlr_foreign_toplevel_manager_v1_add_listener(ctx.toplevel_manager, &foreign_toplevel_manager_listener, NULL);
}
if (strcmp(interface, wl_compositor_interface.name) == 0) {
ctx.compositor = wl_registry_bind(registry, name,
&wl_compositor_interface, 4);
} else if (strcmp(interface, wl_shm_interface.name) == 0) {
ctx.shm = wl_registry_bind(registry, name,
&wl_shm_interface, 1);
} else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
ctx.layer_shell = wl_registry_bind(registry, name,
&zwlr_layer_shell_v1_interface, 1);
} else if (strcmp(interface, wl_seat_interface.name) == 0) {
ctx.seat = wl_registry_bind(registry, name, &wl_seat_interface, 3);
wl_seat_add_listener(ctx.seat, &seat_listener, ctx.seat);
add_seat_to_idle_handler(ctx.seat);
} else if (strcmp(interface, wl_output_interface.name) == 0) {
struct wl_output *output =
wl_registry_bind(registry, name, &wl_output_interface, 3);
create_output(output, name);
} else if (strcmp(interface, org_kde_kwin_idle_interface.name) == 0 &&
version >= ORG_KDE_KWIN_IDLE_TIMEOUT_IDLE_SINCE_VERSION) {
ctx.idle_handler = wl_registry_bind(registry, name, &org_kde_kwin_idle_interface, 1);
}
}
@ -529,38 +320,31 @@ static const struct wl_registry_listener registry_listener = {
.global_remove = handle_global_remove,
};
bool wl_init() {
bool init_wayland() {
wl_list_init(&ctx.outputs);
//wl_list_init(&ctx.seats); // TODO multi-seat support
//wl_list_init(&ctx.seats);
ctx.display = wl_display_connect(NULL);
if (ctx.display == NULL) {
LOG_W("failed to create display");
LOG_E("failed to create display");
return false;
}
int count = 0;
ctx.registry = wl_display_get_registry(ctx.display);
wl_registry_add_listener(ctx.registry, &registry_listener, &count);
wl_display_roundtrip(ctx.display);
count = 1;
// we need a second pass to let for foreign_toplevel (look there for more info)
ctx.registry = wl_display_get_registry(ctx.display);
wl_registry_add_listener(ctx.registry, &registry_listener, &count);
wl_registry_add_listener(ctx.registry, &registry_listener, NULL);
wl_display_roundtrip(ctx.display);
if (ctx.compositor == NULL) {
LOG_W("compositor doesn't support wl_compositor");
LOG_E("compositor doesn't support wl_compositor");
return false;
}
if (ctx.shm == NULL) {
LOG_W("compositor doesn't support wl_shm");
LOG_E("compositor doesn't support wl_shm");
return false;
}
if (ctx.layer_shell == NULL) {
LOG_W("compositor doesn't support zwlr_layer_shell_v1");
LOG_E("compositor doesn't support zwlr_layer_shell_v1");
return false;
}
if (ctx.seat == NULL) {
@ -575,17 +359,10 @@ bool wl_init() {
}
}
if (ctx.toplevel_manager == NULL) {
LOG_W("compositor doesn't support zwlr_foreign_toplevel_v1. Fullscreen detection won't work");
}
return true;
}
void wl_deinit() {
// We need to check if any of these are NULL, since the initialization
// could have been aborted half way through, or the compositor doesn't
// support some of these features.
void finish_wayland() {
if (ctx.layer_surface != NULL) {
zwlr_layer_surface_v1_destroy(ctx.layer_surface);
}
@ -595,47 +372,56 @@ void wl_deinit() {
finish_buffer(&ctx.buffers[0]);
finish_buffer(&ctx.buffers[1]);
// The output list is initialized at the start of init, so no need to
// check for NULL
struct dunst_output *output, *output_tmp;
wl_list_for_each_safe(output, output_tmp, &ctx.outputs, link) {
destroy_output(output);
}
if (ctx.seat) {
if (ctx.pointer.wl_pointer)
wl_pointer_release(ctx.pointer.wl_pointer);
wl_pointer_release(ctx.pointer.wl_pointer);
wl_seat_release(ctx.seat);
ctx.seat = NULL;
}
if (ctx.idle_handler)
org_kde_kwin_idle_destroy(ctx.idle_handler);
zwlr_layer_shell_v1_destroy(ctx.layer_shell);
wl_compositor_destroy(ctx.compositor);
wl_shm_destroy(ctx.shm);
wl_registry_destroy(ctx.registry);
wl_display_disconnect(ctx.display);
if (ctx.idle_timeout)
org_kde_kwin_idle_timeout_release(ctx.idle_timeout);
org_kde_kwin_idle_destroy(ctx.idle_handler);
org_kde_kwin_idle_timeout_release(ctx.idle_timeout);
}
if (ctx.layer_shell)
zwlr_layer_shell_v1_destroy(ctx.layer_shell);
static struct dunst_output *get_configured_output() {
struct dunst_output *output;
if (ctx.compositor)
wl_compositor_destroy(ctx.compositor);
switch (settings.f_mode){
case FOLLOW_NONE: ; // this semicolon is neccesary
int n = 0;
int target_monitor = settings.monitor;
if (ctx.shm)
wl_shm_destroy(ctx.shm);
if (ctx.registry)
wl_registry_destroy(ctx.registry);
if (ctx.display)
wl_display_disconnect(ctx.display);
wl_list_for_each(output, &ctx.outputs, link) {
if (n == target_monitor)
return output;
n++;
}
LOG_W("Monitor %i doesn't exist, using focused monitor", settings.monitor);
return NULL;
case FOLLOW_MOUSE:
// fallthrough
case FOLLOW_KEYBOARD:
// fallthrough
default:
return NULL;
}
}
static void schedule_frame_and_commit();
// Draw and commit a new frame.
static void send_frame() {
int scale = wl_get_scale();
int scale = 1;
struct dunst_output *output = get_configured_output();
int height = ctx.cur_dim.h;
@ -669,13 +455,11 @@ static void send_frame() {
// different output), we need to create it.
if (ctx.layer_surface == NULL) {
struct wl_output *wl_output = NULL;
if (output != NULL) {
wl_output = output->wl_output;
}
ctx.layer_surface_output = output;
ctx.surface = wl_compositor_create_surface(ctx.compositor);
wl_surface_add_listener(ctx.surface, &surface_listener, NULL);
if (settings.frame_color)
ctx.layer_surface = zwlr_layer_shell_v1_get_layer_surface(
ctx.layer_shell, ctx.surface, wl_output,
settings.layer, "notifications");
@ -701,6 +485,8 @@ static void send_frame() {
if (ctx.height != height || ctx.width != width) {
struct dimensions dim = ctx.cur_dim;
// Set window size
LOG_D("Window dimensions %ix%i", dim.w, dim.h);
LOG_D("Window position %ix%i", dim.x, dim.y);
zwlr_layer_surface_v1_set_size(ctx.layer_surface,
dim.w, dim.h);
@ -796,6 +582,13 @@ void set_dirty() {
schedule_frame_and_commit();
}
void wl_init(void) {
init_wayland();
}
void wl_deinit(void) {
}
window wl_win_create(void) {
struct window_wl *win = g_malloc0(sizeof(struct window_wl));
@ -812,8 +605,6 @@ void wl_win_destroy(window winptr) {
}
void wl_win_show(window win) {
// This is here for compatibilty with the X11 output. The window is
// already shown in wl_display_surface.
}
void wl_win_hide(window win) {
@ -825,15 +616,12 @@ void wl_win_hide(window win) {
void wl_display_surface(cairo_surface_t *srf, window winptr, const struct dimensions* dim) {
/* struct window_wl *win = (struct window_wl*)winptr; */
int scale = wl_get_scale();
LOG_D("Buffer size (scaled) %ix%i", dim->w * scale, dim->h * scale);
ctx.current_buffer = get_next_buffer(ctx.shm, ctx.buffers,
dim->w * scale, dim->h * scale);
ctx.current_buffer = get_next_buffer(ctx.shm, ctx.buffers, dim->w, dim->h);
cairo_t *c = ctx.current_buffer->cairo;
cairo_save(c);
cairo_set_source_surface(c, srf, 0, 0);
cairo_rectangle(c, 0, 0, dim->w * scale, dim->h * scale);
cairo_rectangle(c, 0, 0, dim->w, dim->h);
cairo_fill(c);
cairo_restore(c);
@ -843,6 +631,10 @@ void wl_display_surface(cairo_surface_t *srf, window winptr, const struct dimens
wl_display_roundtrip(ctx.display);
}
bool wl_win_visible(window win) {
return true;
}
cairo_t* wl_win_get_context(window winptr) {
struct window_wl *win = (struct window_wl*)winptr;
ctx.current_buffer = get_next_buffer(ctx.shm, ctx.buffers, 500, 500);
@ -861,7 +653,6 @@ const struct screen_info* wl_get_active_screen(void) {
.id = 0,
.mmh = 500
};
scr.dpi = wl_get_scale() * 96;
return &scr;
}
@ -875,43 +666,7 @@ bool wl_is_idle(void) {
return ctx.is_idle;
}
}
bool wl_have_fullscreen_window(void) {
bool have_fullscreen = false;
struct dunst_output *current_output = get_configured_output();
if (!current_output) {
// Cannot detect focused output, so return true if any of the
// outputs is fullscreen. This will work even when unfocused
// outputs have fullscreen toplevels, since a toplevel has to
// be fullscreen and activate to consider an output fullscreen.
struct dunst_output *output;
wl_list_for_each(output, &ctx.outputs, link) {
have_fullscreen |= output->fullscreen;
}
} else {
have_fullscreen = current_output->fullscreen;
}
LOG_D("Fullscreen queried: %i", have_fullscreen);
return have_fullscreen;
}
int wl_get_scale(void) {
int scale = 0;
struct dunst_output *output = get_configured_output();
if (output) {
scale = output->scale;
} else {
// return the largest scale
struct dunst_output *output;
wl_list_for_each(output, &ctx.outputs, link) {
scale = MAX(output->scale, scale);
}
}
if (scale <= 0)
scale = 1;
return scale;
return false;
}
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */

View File

@ -7,7 +7,7 @@
#include "../output.h"
bool wl_init(void);
void wl_init(void);
void wl_deinit(void);
window wl_win_create(void);
@ -17,16 +17,12 @@ void wl_win_show(window);
void wl_win_hide(window);
void wl_display_surface(cairo_surface_t *srf, window win, const struct dimensions*);
bool wl_win_visible(window);
cairo_t* wl_win_get_context(window);
const struct screen_info* wl_get_active_screen(void);
bool wl_is_idle(void);
bool wl_have_fullscreen_window(void);
// Return the dpi scaling of the current output. Everything that's rendered
// should be multiplied by this value, but don't use it to multiply other
// values. All sizes should be in unscaled units.
int wl_get_scale(void);
#endif
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */

View File

@ -113,7 +113,7 @@ static void x_win_corners_shape(struct window_x11 *win, const int rad)
draw_rounded_rect(cr, 0, 0,
width, height,
rad, 1,
rad,
true, true);
cairo_fill(cr);
@ -179,6 +179,11 @@ void x_display_surface(cairo_surface_t *srf, window winptr, const struct dimensi
}
bool x_win_visible(window winptr)
{
return ((struct window_x11*)winptr)->visible;
}
cairo_t* x_win_get_context(window winptr)
{
return ((struct window_x11*)win)->c_ctx;
@ -496,16 +501,14 @@ static void XRM_update_db(void)
/*
* Setup X11 stuff
*/
bool x_setup(void)
void x_setup(void)
{
/* initialize xctx.dc, font, keyboard, colors */
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
LOG_W("No locale support");
if (!(xctx.dpy = XOpenDisplay(NULL))) {
LOG_W("Cannot open X11 display.");
return false;
DIE("Cannot open X11 display.");
}
x_shortcut_init(&settings.close_ks);
@ -529,7 +532,6 @@ bool x_setup(void)
init_screens();
x_shortcut_grab(&settings.history_ks);
return true;
}
struct geometry x_parse_geometry(const char *geom_str)
@ -942,8 +944,4 @@ static void x_shortcut_init(struct keyboard_shortcut *ks)
g_free(str_begin);
}
int x_get_scale(void) {
return 1;
}
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */

View File

@ -42,15 +42,15 @@ void x_win_hide(window);
void x_display_surface(cairo_surface_t *srf, window, const struct dimensions *dim);
bool x_win_visible(window);
cairo_t* x_win_get_context(window);
/* X misc */
bool x_is_idle(void);
bool x_setup(void);
void x_setup(void);
void x_free(void);
struct geometry x_parse_geometry(const char *geom_str);
int x_get_scale(void);
#endif
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */

View File

@ -686,7 +686,6 @@ TEST test_server_caps(enum markup_mode markup)
ASSERT(g_strv_contains(capsarray, "actions"));
ASSERT(g_strv_contains(capsarray, "body"));
ASSERT(g_strv_contains(capsarray, "body-hyperlinks"));
ASSERT(g_strv_contains(capsarray, "icon-static"));
ASSERT(g_strv_contains(capsarray, "x-dunst-stack-tag"));
if (settings.markup != MARKUP_NO)
@ -857,10 +856,6 @@ SUITE(suite_dbus)
loop = g_main_loop_new(NULL, false);
dbus_bus = g_test_dbus_new(G_TEST_DBUS_NONE);
// workaround bug in glib where stdout output is duplicated
// See https://gitlab.gnome.org/GNOME/glib/-/issues/2322
fflush(stdout);
g_test_dbus_up(dbus_bus);
thread_tests = g_thread_new("testexecutor", run_threaded_tests, loop);

View File

@ -12,8 +12,6 @@
extern const char *base;
int scale = 1;
TEST test_get_path_from_icon_null(void){
char *result = get_path_from_icon_name(NULL);
ASSERT_EQ(result, NULL);
@ -88,7 +86,7 @@ TEST test_get_pixbuf_from_file_tilde(void)
gchar *path = g_build_filename(base, iconpath, "valid", "icon1.svg", NULL);
path = string_replace_at(path, 0, strlen(home), "~");
GdkPixbuf *pixbuf = get_pixbuf_from_file(path, scale);
GdkPixbuf *pixbuf = get_pixbuf_from_file(path);
g_clear_pointer(&path, g_free);
ASSERT(pixbuf);
@ -103,7 +101,7 @@ TEST test_get_pixbuf_from_file_absolute(void)
gchar *path = g_build_filename(base, iconpath, "valid", "icon1.svg", NULL);
GdkPixbuf *pixbuf = get_pixbuf_from_file(path, scale);
GdkPixbuf *pixbuf = get_pixbuf_from_file(path);
g_clear_pointer(&path, g_free);
ASSERT(pixbuf);
@ -115,7 +113,7 @@ TEST test_get_pixbuf_from_file_absolute(void)
TEST test_get_pixbuf_from_icon_invalid(void)
{
GdkPixbuf *pixbuf = get_pixbuf_from_icon("invalid", scale);
GdkPixbuf *pixbuf = get_pixbuf_from_icon("invalid");
ASSERT(pixbuf == NULL);
g_clear_pointer(&pixbuf, g_object_unref);
@ -124,7 +122,7 @@ TEST test_get_pixbuf_from_icon_invalid(void)
TEST test_get_pixbuf_from_icon_both(void)
{
GdkPixbuf *pixbuf = get_pixbuf_from_icon("icon1", scale);
GdkPixbuf *pixbuf = get_pixbuf_from_icon("icon1");
// the first icon found is invalid, so the pixbuf is empty
ASSERT(!pixbuf);
g_clear_pointer(&pixbuf, g_object_unref);
@ -134,7 +132,7 @@ TEST test_get_pixbuf_from_icon_both(void)
TEST test_get_pixbuf_from_icon_onlysvg(void)
{
GdkPixbuf *pixbuf = get_pixbuf_from_icon("onlysvg", scale);
GdkPixbuf *pixbuf = get_pixbuf_from_icon("onlysvg");
ASSERT(pixbuf);
ASSERTm("SVG pixbuf isn't loaded", IS_ICON_SVG(pixbuf));
g_clear_pointer(&pixbuf, g_object_unref);
@ -144,7 +142,7 @@ TEST test_get_pixbuf_from_icon_onlysvg(void)
TEST test_get_pixbuf_from_icon_onlypng(void)
{
GdkPixbuf *pixbuf = get_pixbuf_from_icon("onlypng", scale);
GdkPixbuf *pixbuf = get_pixbuf_from_icon("onlypng");
ASSERT(pixbuf);
ASSERTm("PNG pixbuf isn't loaded", IS_ICON_PNG(pixbuf));
g_clear_pointer(&pixbuf, g_object_unref);
@ -155,7 +153,7 @@ TEST test_get_pixbuf_from_icon_onlypng(void)
TEST test_get_pixbuf_from_icon_filename(void)
{
char *icon = g_strconcat(base, "/data/icons/valid.png", NULL);
GdkPixbuf *pixbuf = get_pixbuf_from_icon(icon, scale);
GdkPixbuf *pixbuf = get_pixbuf_from_icon(icon);
ASSERT(pixbuf);
ASSERTm("PNG pixbuf isn't loaded", IS_ICON_PNG(pixbuf));
g_clear_pointer(&pixbuf, g_object_unref);
@ -167,7 +165,7 @@ TEST test_get_pixbuf_from_icon_filename(void)
TEST test_get_pixbuf_from_icon_fileuri(void)
{
char *icon = g_strconcat("file://", base, "/data/icons/valid.svg", NULL);
GdkPixbuf *pixbuf = get_pixbuf_from_icon(icon, scale);
GdkPixbuf *pixbuf = get_pixbuf_from_icon(icon);
ASSERT(pixbuf);
ASSERTm("SVG pixbuf isn't loaded", IS_ICON_SVG(pixbuf));
g_clear_pointer(&pixbuf, g_object_unref);
@ -222,7 +220,7 @@ TEST test_icon_size_clamp_too_small_then_too_big(void)
TEST test_get_pixbuf_from_icon_both_is_scaled(void)
{
GdkPixbuf *pixbuf = get_pixbuf_from_icon("onlypng", scale);
GdkPixbuf *pixbuf = get_pixbuf_from_icon("onlypng");
ASSERT(pixbuf);
ASSERT_EQ(gdk_pixbuf_get_width(pixbuf), 16);
ASSERT_EQ(gdk_pixbuf_get_height(pixbuf), 16);

View File

@ -763,68 +763,6 @@ TEST test_queue_find_by_id(void)
PASS();
}
void print_queues() {
printf("\nQueues:\n");
for (GList *iter = g_queue_peek_head_link(QUEUE_WAIT); iter;
iter = iter->next) {
struct notification *notif = iter->data;
printf("waiting %s\n", notif->summary);
}
}
// Test if notifications are correctly sorted, even if dunst is paused in
// between. See #838 for the issue.
TEST test_queue_no_sort_and_pause(void)
{
// Setting sort to false, this means that notifications will only be
// sorted based on time
settings.sort = false;
settings.geometry.h = 0;
struct notification *n;
queues_init();
n = test_notification("n0", 0);
queues_notification_insert(n);
queues_update(STATUS_NORMAL);
n = test_notification("n1", 0);
queues_notification_insert(n);
queues_update(STATUS_NORMAL);
n = test_notification("n2", 0);
queues_notification_insert(n);
queues_update(STATUS_PAUSE);
n = test_notification("n3", 0);
queues_notification_insert(n);
queues_update(STATUS_PAUSE);
/* queues_update(STATUS_NORMAL); */
n = test_notification("n4", 0);
queues_notification_insert(n);
queues_update(STATUS_NORMAL);
QUEUE_LEN_ALL(0, 5, 0);
const char* order[] = {
"n0",
"n1",
"n2",
"n3",
"n4",
};
for (int i = 0; i < g_queue_get_length(QUEUE_DISP); i++) {
struct notification *notif = g_queue_peek_nth(QUEUE_DISP, i);
ASSERTm("Notifications are not in the right order",
STR_EQ(notif->summary, order[i]));
}
queues_teardown();
PASS();
}
SUITE(suite_queues)
{
settings.icon_path = "";
@ -856,7 +794,6 @@ SUITE(suite_queues)
RUN_TEST(test_queues_update_xmore);
RUN_TEST(test_queues_timeout_before_paused);
RUN_TEST(test_queue_find_by_id);
RUN_TEST(test_queue_no_sort_and_pause);
settings.icon_path = NULL;
}