コミットを比較

...

10 コミット

作成者 SHA1 メッセージ 日付
守矢諏訪子 62f4492304 ちんぽ 2023-08-23 22:55:55 +09:00
MadcowOG a5dbf902cf If monitors on the compositor side are disable, they are removed as globals client side.
So we need to recreate them after they are turned back on.
Also, used g_object_unref on PangoFontDescription rather than pango_font_description_free which would cause a crash.
2023-05-12 14:28:26 -07:00
MadcowOG 895bd53e8c Added a reset for axis values after a discete scroll 2023-05-03 22:11:56 -07:00
MadcowOG fe5c722969 Update monitors when we finish creating them. 2023-04-27 23:01:38 -07:00
MadcowOG b75d7cb4e2 Added clarification on tags in config.def.h. 2023-04-27 16:16:35 -07:00
MadcowOG 2568d3cc23 Fixed free on stack problem with shm. 2023-04-26 13:53:52 -07:00
MadcowOG 67cafa3de1 Removed wrong import config.def.h 2023-04-24 18:55:09 -07:00
MadcowOG 4ae6e8d5b1 Messed up list resizing, forgot to multiply allocated amount by the sizeof(void*). 2023-04-22 16:11:51 -07:00
MadcowOG 3a6c255b97 Moved monitor main initialization point to in setup rather than in registry_global_add.
Placing the initialization of the monitor (other than for wl_output and xdg_name) in the registry_global_add can cause problems when we depend on a global for some fields.
2023-04-22 03:26:42 -07:00
MadcowOG cfaa4348e8 Added HotspotListener and renamed prcocess_hotspots to hotspots_process to try and keep up with conventions. 2023-04-22 01:44:58 -07:00
14個のファイルの変更572行の追加192行の削除

ファイルの表示

@ -7,7 +7,7 @@ VERSION = 0.0
PKG_CONFIG = pkg-config
# paths
PREFIX = /usr/local
PREFIX = /usr
MANDIR = $(PREFIX)/share/man
SRCDIR = src
@ -19,6 +19,8 @@ FILES = $(SRCDIR)/main.c $(SRCDIR)/main.h $(SRCDIR)/log.c $(SRCDIR)/log.h \
$(SRCDIR)/bar.c $(SRCDIR)/bar.h $(SRCDIR)/config.h
OBJS = $(SRCDIR)/xdg-output-unstable-v1-protocol.o $(SRCDIR)/xdg-shell-protocol.o \
$(SRCDIR)/wlr-layer-shell-unstable-v1-protocol.o
OBJS := $(filter-out $(SRCDIR)/xdg-output-unstable-v1-protocol.o,$(OBJS))
OBJS += $(SRCDIR)/dwl-ipc-unstable-v2-protocol.o
## Compile Flags
CC = gcc
@ -42,13 +44,6 @@ $(SRCDIR)/xdg-shell-protocol.c:
$(WAYLAND_SCANNER) private-code \
$(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@
$(SRCDIR)/xdg-output-unstable-v1-protocol.h:
$(WAYLAND_SCANNER) client-header \
$(WAYLAND_PROTOCOLS)/unstable/xdg-output/xdg-output-unstable-v1.xml $@
$(SRCDIR)/xdg-output-unstable-v1-protocol.c:
$(WAYLAND_SCANNER) private-code \
$(WAYLAND_PROTOCOLS)/unstable/xdg-output/xdg-output-unstable-v1.xml $@
$(SRCDIR)/wlr-layer-shell-unstable-v1-protocol.h:
$(WAYLAND_SCANNER) client-header \
protocols/wlr-layer-shell-unstable-v1.xml $@
@ -56,6 +51,13 @@ $(SRCDIR)/wlr-layer-shell-unstable-v1-protocol.c:
$(WAYLAND_SCANNER) private-code \
protocols/wlr-layer-shell-unstable-v1.xml $@
$(SRCDIR)/dwl-ipc-unstable-v2-protocol.h:
$(WAYLAND_SCANNER) client-header \
protocols/dwl-ipc-unstable-v2.xml $@
$(SRCDIR)/dwl-ipc-unstable-v2-protocol.c:
$(WAYLAND_SCANNER) private-code \
protocols/dwl-ipc-unstable-v2.xml $@
$(SRCDIR)/config.h:
cp src/config.def.h $@

181
dwl-ipc-unstable-v2.xml ノーマルファイル
ファイルの表示

@ -0,0 +1,181 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This is largely ripped from somebar's ipc patchset; just with some personal modifications.
I would probably just submit raphi's patchset but I don't think that would be polite.
-->
<protocol name="dwl_ipc_unstable_v2">
<description summary="inter-proccess-communication about dwl's state">
This protocol allows clients to update and get updates from dwl.
Warning! The protocol described in this file is experimental and
backward incompatible changes may be made. Backward compatible
changes may be added together with the corresponding interface
version bump.
Backward incompatible changes are done by bumping the version
number in the protocol and interface names and resetting the
interface version. Once the protocol is to be declared stable,
the 'z' prefix and the version number in the protocol and
interface names are removed and the interface version number is
reset.
</description>
<interface name="zdwl_ipc_manager_v2" version="2">
<description summary="manage dwl state">
This interface is exposed as a global in wl_registry.
Clients can use this interface to get a dwl_ipc_output.
After binding the client will recieve the dwl_ipc_manager.tags and dwl_ipc_manager.layout events.
The dwl_ipc_manager.tags and dwl_ipc_manager.layout events expose tags and layouts to the client.
</description>
<request name="release" type="destructor">
<description summary="release dwl_ipc_manager">
Indicates that the client will not the dwl_ipc_manager object anymore.
Objects created through this instance are not affected.
</description>
</request>
<request name="get_output">
<description summary="get a dwl_ipc_outout for a wl_output">
Get a dwl_ipc_outout for the specified wl_output.
</description>
<arg name="id" type="new_id" interface="zdwl_ipc_output_v2"/>
<arg name="output" type="object" interface="wl_output"/>
</request>
<event name="tags">
<description summary="Announces tag amount">
This event is sent after binding.
A roundtrip after binding guarantees the client recieved all tags.
</description>
<arg name="amount" type="uint"/>
</event>
<event name="layout">
<description summary="Announces a layout">
This event is sent after binding.
A roundtrip after binding guarantees the client recieved all layouts.
</description>
<arg name="name" type="string"/>
</event>
</interface>
<interface name="zdwl_ipc_output_v2" version="2">
<description summary="control dwl output">
Observe and control a dwl output.
Events are double-buffered:
Clients should cache events and redraw when a dwl_ipc_output.frame event is sent.
Request are not double-buffered:
The compositor will update immediately upon request.
</description>
<enum name="tag_state">
<entry name="none" value="0" summary="no state"/>
<entry name="active" value="1" summary="tag is active"/>
<entry name="urgent" value="2" summary="tag has at least one urgent client"/>
</enum>
<request name="release" type="destructor">
<description summary="release dwl_ipc_outout">
Indicates to that the client no longer needs this dwl_ipc_output.
</description>
</request>
<event name="toggle_visibility">
<description summary="Toggle client visibilty">
Indicates the client should hide or show themselves.
If the client is visible then hide, if hidden then show.
</description>
</event>
<event name="active">
<description summary="Update the selected output.">
Indicates if the output is active. Zero is invalid, nonzero is valid.
</description>
<arg name="active" type="uint"/>
</event>
<event name="tag">
<description summary="Update the state of a tag.">
Indicates that a tag has been updated.
</description>
<arg name="tag" type="uint" summary="Index of the tag"/>
<arg name="state" type="uint" enum="tag_state" summary="The state of the tag."/>
<arg name="clients" type="uint" summary="The number of clients in the tag."/>
<arg name="focused" type="uint" summary="If there is a focused client. Nonzero being valid, zero being invalid."/>
</event>
<event name="layout">
<description summary="Update the layout.">
Indicates a new layout is selected.
</description>
<arg name="layout" type="uint" summary="Index of the layout."/>
</event>
<event name="title">
<description summary="Update the title.">
Indicates the title has changed.
</description>
<arg name="title" type="string" summary="The new title name."/>
</event>
<event name="appid" since="1">
<description summary="Update the appid.">
Indicates the appid has changed.
</description>
<arg name="appid" type="string" summary="The new appid."/>
</event>
<event name="layout_symbol" since="1">
<description summary="Update the current layout symbol">
Indicates the layout has changed. Since layout symbols are dynamic.
As opposed to the zdwl_ipc_manager.layout event, this should take precendence when displaying.
You can ignore the zdwl_ipc_output.layout event.
</description>
<arg name="layout" type="string" summary="The new layout"/>
</event>
<event name="frame">
<description summary="The update sequence is done.">
Indicates that a sequence of status updates have finished and the client should redraw.
</description>
</event>
<request name="set_tags">
<description summary="Set the active tags of this output"/>
<arg name="tagmask" type="uint" summary="bitmask of the tags that should be set."/>
<arg name="toggle_tagset" type="uint" summary="toggle the selected tagset, zero for invalid, nonzero for valid."/>
</request>
<request name="set_client_tags">
<description summary="Set the tags of the focused client.">
The tags are updated as follows:
new_tags = (current_tags AND and_tags) XOR xor_tags
</description>
<arg name="and_tags" type="uint"/>
<arg name="xor_tags" type="uint"/>
</request>
<request name="set_layout">
<description summary="Set the layout of this output"/>
<arg name="index" type="uint" summary="index of a layout recieved by dwl_ipc_manager.layout"/>
</request>
<!-- Version 2 -->
<event name="fullscreen" since="2">
<description summary="Update fullscreen status">
Indicates if the selected client on this output is fullscreen.
</description>
<arg name="is_fullscreen" type="uint" summary="If the selected client is fullscreen. Nonzero is valid, zero invalid"/>
</event>
<event name="floating" since="2">
<description summary="Update the floating status">
Indicates if the selected client on this output is floating.
</description>
<arg name="is_floating" type="uint" summary="If the selected client is floating. Nonzero is valid, zero invalid"/>
</event>
</interface>
</protocol>

181
protocols/dwl-ipc-unstable-v2.xml ノーマルファイル
ファイルの表示

@ -0,0 +1,181 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This is largely ripped from somebar's ipc patchset; just with some personal modifications.
I would probably just submit raphi's patchset but I don't think that would be polite.
-->
<protocol name="dwl_ipc_unstable_v2">
<description summary="inter-proccess-communication about dwl's state">
This protocol allows clients to update and get updates from dwl.
Warning! The protocol described in this file is experimental and
backward incompatible changes may be made. Backward compatible
changes may be added together with the corresponding interface
version bump.
Backward incompatible changes are done by bumping the version
number in the protocol and interface names and resetting the
interface version. Once the protocol is to be declared stable,
the 'z' prefix and the version number in the protocol and
interface names are removed and the interface version number is
reset.
</description>
<interface name="zdwl_ipc_manager_v2" version="2">
<description summary="manage dwl state">
This interface is exposed as a global in wl_registry.
Clients can use this interface to get a dwl_ipc_output.
After binding the client will recieve the dwl_ipc_manager.tags and dwl_ipc_manager.layout events.
The dwl_ipc_manager.tags and dwl_ipc_manager.layout events expose tags and layouts to the client.
</description>
<request name="release" type="destructor">
<description summary="release dwl_ipc_manager">
Indicates that the client will not the dwl_ipc_manager object anymore.
Objects created through this instance are not affected.
</description>
</request>
<request name="get_output">
<description summary="get a dwl_ipc_outout for a wl_output">
Get a dwl_ipc_outout for the specified wl_output.
</description>
<arg name="id" type="new_id" interface="zdwl_ipc_output_v2"/>
<arg name="output" type="object" interface="wl_output"/>
</request>
<event name="tags">
<description summary="Announces tag amount">
This event is sent after binding.
A roundtrip after binding guarantees the client recieved all tags.
</description>
<arg name="amount" type="uint"/>
</event>
<event name="layout">
<description summary="Announces a layout">
This event is sent after binding.
A roundtrip after binding guarantees the client recieved all layouts.
</description>
<arg name="name" type="string"/>
</event>
</interface>
<interface name="zdwl_ipc_output_v2" version="2">
<description summary="control dwl output">
Observe and control a dwl output.
Events are double-buffered:
Clients should cache events and redraw when a dwl_ipc_output.frame event is sent.
Request are not double-buffered:
The compositor will update immediately upon request.
</description>
<enum name="tag_state">
<entry name="none" value="0" summary="no state"/>
<entry name="active" value="1" summary="tag is active"/>
<entry name="urgent" value="2" summary="tag has at least one urgent client"/>
</enum>
<request name="release" type="destructor">
<description summary="release dwl_ipc_outout">
Indicates to that the client no longer needs this dwl_ipc_output.
</description>
</request>
<event name="toggle_visibility">
<description summary="Toggle client visibilty">
Indicates the client should hide or show themselves.
If the client is visible then hide, if hidden then show.
</description>
</event>
<event name="active">
<description summary="Update the selected output.">
Indicates if the output is active. Zero is invalid, nonzero is valid.
</description>
<arg name="active" type="uint"/>
</event>
<event name="tag">
<description summary="Update the state of a tag.">
Indicates that a tag has been updated.
</description>
<arg name="tag" type="uint" summary="Index of the tag"/>
<arg name="state" type="uint" enum="tag_state" summary="The state of the tag."/>
<arg name="clients" type="uint" summary="The number of clients in the tag."/>
<arg name="focused" type="uint" summary="If there is a focused client. Nonzero being valid, zero being invalid."/>
</event>
<event name="layout">
<description summary="Update the layout.">
Indicates a new layout is selected.
</description>
<arg name="layout" type="uint" summary="Index of the layout."/>
</event>
<event name="title">
<description summary="Update the title.">
Indicates the title has changed.
</description>
<arg name="title" type="string" summary="The new title name."/>
</event>
<event name="appid" since="1">
<description summary="Update the appid.">
Indicates the appid has changed.
</description>
<arg name="appid" type="string" summary="The new appid."/>
</event>
<event name="layout_symbol" since="1">
<description summary="Update the current layout symbol">
Indicates the layout has changed. Since layout symbols are dynamic.
As opposed to the zdwl_ipc_manager.layout event, this should take precendence when displaying.
You can ignore the zdwl_ipc_output.layout event.
</description>
<arg name="layout" type="string" summary="The new layout"/>
</event>
<event name="frame">
<description summary="The update sequence is done.">
Indicates that a sequence of status updates have finished and the client should redraw.
</description>
</event>
<request name="set_tags">
<description summary="Set the active tags of this output"/>
<arg name="tagmask" type="uint" summary="bitmask of the tags that should be set."/>
<arg name="toggle_tagset" type="uint" summary="toggle the selected tagset, zero for invalid, nonzero for valid."/>
</request>
<request name="set_client_tags">
<description summary="Set the tags of the focused client.">
The tags are updated as follows:
new_tags = (current_tags AND and_tags) XOR xor_tags
</description>
<arg name="and_tags" type="uint"/>
<arg name="xor_tags" type="uint"/>
</request>
<request name="set_layout">
<description summary="Set the layout of this output"/>
<arg name="index" type="uint" summary="index of a layout recieved by dwl_ipc_manager.layout"/>
</request>
<!-- Version 2 -->
<event name="fullscreen" since="2">
<description summary="Update fullscreen status">
Indicates if the selected client on this output is fullscreen.
</description>
<arg name="is_fullscreen" type="uint" summary="If the selected client is fullscreen. Nonzero is valid, zero invalid"/>
</event>
<event name="floating" since="2">
<description summary="Update the floating status">
Indicates if the selected client on this output is floating.
</description>
<arg name="is_floating" type="uint" summary="If the selected client is floating. Nonzero is valid, zero invalid"/>
</event>
</interface>
</protocol>

ファイルの表示

@ -1,6 +1,5 @@
#include "bar.h"
#include "cairo.h"
#include "config.def.h"
#include "config.h"
#include "input.h"
#include "main.h"
@ -27,6 +26,7 @@ static void bar_status_render(struct Pipeline *pipeline, struct Bar *bar, cairo_
static int bar_width(struct Pipeline *pipeline, void *data, unsigned int future_widths);
const struct PipelineListener bar_pipeline_listener = { .render = bar_render, .width = bar_width, };
const struct HotspotListener bar_hotspot_listener = { .click = bar_click, .bounds = bar_bounds };
void bar_click(struct Monitor *monitor, void *data, uint32_t button, double x, double y) {
if (!monitor || !data)
@ -155,8 +155,7 @@ struct Bar *bar_create(struct List *hotspots, struct Pipeline *pipeline) {
pipeline_add(pipeline, &bar_pipeline_listener, bar);
struct Hotspot *hotspot = list_add(hotspots, ecalloc(1, sizeof(*hotspot)));
hotspot->click = bar_click;
hotspot->bounds = bar_bounds;
hotspot->listener = &bar_hotspot_listener;
hotspot->data = bar;
bar->x = 0;

ファイルの表示

@ -5,6 +5,7 @@
#include <stdlib.h>
#include <linux/input-event-codes.h>
static const int show_bar = 1;
static const int bar_top = 1; /* Boolean value, non-zero is true. If not top then bottom */
static const int status_on_active = 1; /* Display the status on active monitor only. If not then on all. */
static const char *font = "Monospace 10";
@ -16,25 +17,26 @@ static const char *terminal[] = { "alacritty", NULL };
* The color scheming format is the same as dwm.
* We use an enum as a index for our scheme types.
*
* cyan - used in an active background
* magenta - used in an active background
* grey3 - used in active text and urgent background
* grey1 - used in an inactive background
* grey2 - used in inactive text
*/
static const int cyan[4] = { 0, 85, 119, 255 };
static const int grey1[4] = { 34, 34, 34, 255 };
static const int grey2[4] = { 187, 187, 187, 255 };
static const int grey3[4] = { 238, 238, 238, 255 };
static const int magenta[4] = { 234, 129, 232, 255 };
static const int grey1[4] = { 40, 27, 56, 255 };
static const int grey2[4] = { 252, 252, 252, 255 };
static const int grey3[4] = { 35, 38, 41, 255 };
static const int *schemes[3][2] = {
/* Scheme Type fg, bg */
[InActive_Scheme] = {grey2, grey1},
[Active_Scheme] = {grey3, cyan},
[Active_Scheme] = {grey3, magenta},
[Urgent_Scheme] = {grey1, grey3},
};
/*
* Tags
* Must not exceed 31 tags and amount must match dwl's tagcount.
*/
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
@ -44,7 +46,12 @@ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
*/
static const Binding bindings[] = {
/* Click Location, button, callback, bypass, arguments */
{ Click_Layout, BTN_LEFT, layout, 1, {.ui = 0} },
{ Click_Layout, BTN_RIGHT, layout, 1, {.ui = 1} },
{ Click_Status, BTN_MIDDLE, spawn, 0, {.v = terminal } },
{ Click_Tag, BTN_MIDDLE, tag, 0, {0} },
{ Click_Tag, BTN_RIGHT, toggle_view, 0, {0} },
{ Click_Tag, BTN_LEFT, view, 0, {0} },
};
#endif // CONFIG_H_

ファイルの表示

@ -15,6 +15,7 @@
#include <wayland-util.h>
static int button_cmp(const void *left, const void *right);
static void hotspots_process(struct Monitor* monitor, double x, double y, uint32_t button);
static void pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value);
static void pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, uint32_t axis, int32_t discrete);
static void pointer_axis_source(void *data, struct wl_pointer *wl_pointer, uint32_t axis_source);
@ -158,7 +159,7 @@ void pointer_frame(void *data, struct wl_pointer *wl_pointer) {
if (!monitor) return;
for (int i = 0; i < pointer->buttons->length; i++)
process_hotspots(pointer->focused_monitor, pointer->x, pointer->y,
hotspots_process(pointer->focused_monitor, pointer->x, pointer->y,
*(uint32_t*)pointer->buttons->data[i]);
list_elements_destroy(pointer->buttons, free);
pointer->buttons = list_create(0);
@ -173,14 +174,16 @@ void pointer_process_scroll(struct Pointer *pointer, unsigned int axis_index) {
struct Axis *axis = &pointer->axis[axis_index];
if (axis->discrete_steps) {
for (int i = 0; i < axis->discrete_steps; i++)
process_hotspots(pointer->focused_monitor, pointer->x, pointer->y, wl_axis_to_button(axis_index, axis->value));
hotspots_process(pointer->focused_monitor, pointer->x, pointer->y, wl_axis_to_button(axis_index, axis->value));
axis->value = 0;
axis->discrete_steps = 0;
} else {
while (abs(axis->value) > SCROLL_THRESHOLD) {
if (axis->value > 0){
process_hotspots(pointer->focused_monitor, pointer->x, pointer->y, wl_axis_to_button(axis_index, SCROLL_THRESHOLD));
hotspots_process(pointer->focused_monitor, pointer->x, pointer->y, wl_axis_to_button(axis_index, SCROLL_THRESHOLD));
axis->value -= SCROLL_THRESHOLD;
} else {
process_hotspots(pointer->focused_monitor, pointer->x, pointer->y, wl_axis_to_button(axis_index, -SCROLL_THRESHOLD));
hotspots_process(pointer->focused_monitor, pointer->x, pointer->y, wl_axis_to_button(axis_index, -SCROLL_THRESHOLD));
axis->value += SCROLL_THRESHOLD;
}
}
@ -224,19 +227,19 @@ void pointer_update_cursor(struct Pointer *pointer) {
wl_surface_commit(pointer->cursor_surface);
}
void process_hotspots(struct Monitor* monitor, double x, double y, uint32_t button) {
void hotspots_process(struct Monitor* monitor, double x, double y, uint32_t button) {
struct Hotspot *hotspot;
for (int i = 0; i < monitor->hotspots->length; i++) {
hotspot = monitor->hotspots->data[i];
double hotspot_x = 0, hotspot_y = 0, hotspot_width = 0, hotspot_height = 0;
hotspot->bounds(hotspot->data, &hotspot_x, &hotspot_y, &hotspot_width, &hotspot_height);
hotspot->listener->bounds(hotspot->data, &hotspot_x, &hotspot_y, &hotspot_width, &hotspot_height);
if (!( x > hotspot_x && y > hotspot_y &&
x < (hotspot_x+hotspot_width) && y < (hotspot_y+hotspot_height)))
continue;
hotspot->click(monitor, hotspot->data, button, x, y);
hotspot->listener->click(monitor, hotspot->data, button, x, y);
return;
}
}
@ -389,7 +392,7 @@ void touch_up(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t t
if (!point) return;
uint32_t button = touch_point_to_button(point, time);
process_hotspots(point->focused_monitor, point->x, point->y, button);
hotspots_process(point->focused_monitor, point->x, point->y, button);
}
uint32_t wl_axis_to_button(int axis, wl_fixed_t value) {

ファイルの表示

@ -51,15 +51,18 @@ struct Seat {
struct wl_list link;
};
struct Hotspot {
struct HotspotListener {
void (*click)(struct Monitor *monitor, void *data, uint32_t button, double x, double y);
void (*bounds)(void *data, double *x, double *y, double *width, double *height);
};
struct Hotspot {
const struct HotspotListener *listener;
void *data;
};
extern const struct wl_seat_listener seat_listener;
void process_hotspots(struct Monitor* monitor, double x, double y, uint32_t button);
void seat_destroy(struct Seat *seat);
#endif // INPUT_H_

ファイルの表示

@ -1,11 +1,12 @@
#include "bar.h"
#include "config.h"
#include "dwl-ipc-unstable-v2-protocol.h"
#include "event.h"
#include "log.h"
#include "render.h"
#include "util.h"
#include "main.h"
#include "input.h"
#include "xdg-output-unstable-v1-protocol.h"
#include "xdg-shell-protocol.h"
#include "wlr-layer-shell-unstable-v1-protocol.h"
#include <math.h>
@ -33,8 +34,8 @@ static void fifo_handle(const char *line);
static void fifo_in(int fd, short mask, void *data);
static void fifo_setup(void);
static void monitor_destroy(struct Monitor *monitor);
static struct Monitor *monitor_from_name(const char *name);
struct Monitor *monitor_from_surface(const struct wl_surface *surface);
static void monitor_initialize(struct Monitor *monitor);
static void monitor_update(struct Monitor *monitor);
static void pipe_in(int fd, short mask, void *data);
static void registry_global_add(void *data, struct wl_registry *registry, uint32_t name,
@ -43,19 +44,31 @@ static void registry_global_remove(void *data, struct wl_registry *registry, uin
static void run(void);
static void set_cloexec(int fd);
static void setup(void);
static void stdin_handle(const char *line);
static void stdin_in(int fd, short mask, void *data);
static void sigaction_handler(int _);
static void xdg_output_name(void *data, struct zxdg_output_v1 *output, const char *name);
static void xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial);
static void zdwl_ipc_manager_layout(void *data, struct zdwl_ipc_manager_v2 *zdwl_ipc_manager_v2, const char *name);
static void zdwl_ipc_manager_tags(void *data, struct zdwl_ipc_manager_v2 *zdwl_ipc_manager_v2, uint32_t amount);
static void zdwl_ipc_output_active(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t active);
static void zdwl_ipc_output_appid(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, const char *appid);
static void zdwl_ipc_output_floating(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t is_floating);
static void zdwl_ipc_output_frame(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2);
static void zdwl_ipc_output_fullscreen(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t is_fullscreen);
static void zdwl_ipc_output_layout(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t layout);
static void zdwl_ipc_output_layout_symbol(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, const char *layout);
static void zdwl_ipc_output_tag(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2,
uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused);
static void zdwl_ipc_output_title(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, const char *title);
static void zdwl_ipc_output_toggle_visibility(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2);
static struct xdg_wm_base *base;
struct wl_compositor *compositor;
static struct wl_display *display;
static int display_fd;
static struct zdwl_ipc_manager_v2 *dwl_manager = NULL;
static struct Events *events;
static int fifo_fd;
static char *fifo_path;
int layoutcount;
static struct wl_list monitors; // struct Monitor*
static struct zxdg_output_manager_v1 *output_manager;
static const struct wl_registry_listener registry_listener = {
@ -67,12 +80,26 @@ static struct wl_list seats; // struct Seat*
static int self_pipe[2];
struct zwlr_layer_shell_v1 *shell;
struct wl_shm *shm;
static const struct zxdg_output_v1_listener xdg_output_listener = {
.name = xdg_output_name,
};
static int tagcount;
static const struct xdg_wm_base_listener xdg_wm_base_listener = {
.ping = xdg_wm_base_ping,
};
static const struct zdwl_ipc_manager_v2_listener zdwl_manager_listener = {
.layout = zdwl_ipc_manager_layout,
.tags = zdwl_ipc_manager_tags,
};
static const struct zdwl_ipc_output_v2_listener zdwl_output_listener = {
.active = zdwl_ipc_output_active,
.appid = zdwl_ipc_output_appid,
.floating = zdwl_ipc_output_floating,
.frame = zdwl_ipc_output_frame,
.fullscreen = zdwl_ipc_output_fullscreen,
.layout = zdwl_ipc_output_layout,
.layout_symbol = zdwl_ipc_output_layout_symbol,
.tag = zdwl_ipc_output_tag,
.title = zdwl_ipc_output_title,
.toggle_visibility = zdwl_ipc_output_toggle_visibility,
};
void check_global(void *global, const char *name) {
if (global)
@ -83,7 +110,7 @@ void check_global(void *global, const char *name) {
void check_globals(void) {
check_global(base, "xdg_wm_base");
check_global(compositor, "wl_compositor");
check_global(output_manager, "zxdg_output_manager_v1");
check_global(dwl_manager, "zdwl_ipc_manager_v2");
check_global(shell, "zwlr_layer_shell_v1");
check_global(shm, "wl_shm");
}
@ -94,8 +121,8 @@ void cleanup(void) {
close(fifo_fd);
unlink(fifo_path);
free(fifo_path);
zxdg_output_manager_v1_destroy(output_manager);
zwlr_layer_shell_v1_destroy(shell);
zdwl_ipc_manager_v2_destroy(dwl_manager);
wl_shm_destroy(shm);
events_destroy(events);
log_destroy();
@ -195,25 +222,16 @@ void monitor_destroy(struct Monitor *monitor) {
if (!monitor)
return;
wl_list_remove(&monitor->link);
free(monitor->xdg_name);
if (wl_output_get_version(monitor->wl_output) >= WL_OUTPUT_RELEASE_SINCE_VERSION)
wl_output_release(monitor->wl_output);
wl_output_release(monitor->wl_output);
zdwl_ipc_output_v2_destroy(monitor->dwl_output);
list_elements_destroy(monitor->hotspots, free);
pipeline_destroy(monitor->pipeline);
bar_destroy(monitor->bar);
free(monitor);
}
struct Monitor *monitor_from_name(const char *name) {
struct Monitor *pos;
wl_list_for_each(pos, &monitors, link) {
if (STRING_EQUAL(name, pos->xdg_name))
return pos;
}
return NULL;
}
struct Monitor *monitor_from_surface(const struct wl_surface *surface) {
struct Monitor *pos;
wl_list_for_each(pos, &monitors, link) {
@ -224,11 +242,23 @@ struct Monitor *monitor_from_surface(const struct wl_surface *surface) {
return NULL;
}
void monitor_initialize(struct Monitor *monitor) {
if (!monitor) return;
monitor->desired_visibility = show_bar;
monitor->hotspots = list_create(1);
monitor->pipeline = pipeline_create();
monitor->bar = bar_create(monitor->hotspots, monitor->pipeline);
if (!monitor->pipeline || !monitor->bar)
panic("Failed to create a pipline or bar for a monitor");
monitor_update(monitor);
}
void monitor_update(struct Monitor *monitor) {
if (!monitor)
return;
if (!pipeline_is_visible(monitor->pipeline)) {
if (!pipeline_is_visible(monitor->pipeline) && monitor->desired_visibility) {
pipeline_show(monitor->pipeline, monitor->wl_output);
return;
}
@ -255,22 +285,17 @@ void registry_global_add(void *data, struct wl_registry *registry, uint32_t name
struct Monitor *monitor = ecalloc(1, sizeof(*monitor));
monitor->wl_output = wl_registry_bind(registry, name, &wl_output_interface, 1);
monitor->wl_name = name;
monitor->xdg_name = NULL;
monitor->xdg_output = NULL;
monitor->hotspots = list_create(1);
monitor->pipeline = pipeline_create();
monitor->bar = bar_create(monitor->hotspots, monitor->pipeline);
if (!monitor->pipeline || !monitor->bar)
return;
monitor->dwl_output = NULL;
wl_list_insert(&monitors, &monitor->link);
if (!output_manager)
return;
if (!dwl_manager) return;
monitor->xdg_output = zxdg_output_manager_v1_get_xdg_output(output_manager, monitor->wl_output);
zxdg_output_v1_add_listener(monitor->xdg_output, &xdg_output_listener, monitor);
monitor->dwl_output = zdwl_ipc_manager_v2_get_output(dwl_manager, monitor->wl_output);
zdwl_ipc_output_v2_add_listener(monitor->dwl_output, &zdwl_output_listener, monitor);
if (!running) return;
monitor_initialize(monitor);
}
else if (STRING_EQUAL(interface, wl_seat_interface.name)) {
struct Seat *seat = ecalloc(1, sizeof(*seat));
@ -287,17 +312,16 @@ void registry_global_add(void *data, struct wl_registry *registry, uint32_t name
base = wl_registry_bind(registry, name, &xdg_wm_base_interface, 2);
xdg_wm_base_add_listener(base, &xdg_wm_base_listener, NULL);
}
else if (STRING_EQUAL(interface, zxdg_output_manager_v1_interface.name)) {
output_manager = wl_registry_bind(registry, name, &zxdg_output_manager_v1_interface, 3);
else if (STRING_EQUAL(interface, zdwl_ipc_manager_v2_interface.name)) {
dwl_manager = wl_registry_bind(registry, name, &zdwl_ipc_manager_v2_interface, 2);
zdwl_ipc_manager_v2_add_listener(dwl_manager, &zdwl_manager_listener, NULL);
struct Monitor *pos;
wl_list_for_each(pos, &monitors, link) {
// If the monitor is getting or has the xdg_name.
if (pos->xdg_output || pos->xdg_name)
continue;
struct Monitor *monitor;
wl_list_for_each(monitor, &monitors, link) {
if (monitor->dwl_output) continue;
pos->xdg_output = zxdg_output_manager_v1_get_xdg_output(output_manager, pos->wl_output);
zxdg_output_v1_add_listener(pos->xdg_output, &xdg_output_listener, pos);
monitor->dwl_output = zdwl_ipc_manager_v2_get_output(dwl_manager, monitor->wl_output);
zdwl_ipc_output_v2_add_listener(monitor->dwl_output, &zdwl_output_listener, monitor);
}
}
else if (STRING_EQUAL(interface, zwlr_layer_shell_v1_interface.name))
@ -378,136 +402,91 @@ void setup(void) {
wl_display_roundtrip(display);
if (tagcount != LENGTH(tags))
panic("We do not have the same amount of tags as dwl! Please check config.def.h!");
struct Monitor *monitor;
wl_list_for_each(monitor, &monitors, link) {
monitor_initialize(monitor);
}
if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK) < 0)
panic("STDIN_FILENO O_NONBLOCK");
events = events_create();
events_add(events, display_fd, POLLIN, NULL, display_in);
events_add(events, self_pipe[0], POLLIN, NULL, pipe_in);
events_add(events, STDIN_FILENO, POLLIN, NULL, stdin_in);
events_add(events, fifo_fd, POLLIN, NULL, fifo_in);
}
void stdin_handle(const char *line) {
if (!line)
return;
char *name, *command;
struct Monitor *monitor;
unsigned long loc = 0; /* Keep track of where we are in the string `line` */
name = to_delimiter(line, &loc, ' ');
command = to_delimiter(line, &loc, ' ');
monitor = monitor_from_name(name);
if (!monitor) {
free(name);
free(command);
return;
}
free(name);
if (STRING_EQUAL(command, "title")) {
char *title = to_delimiter(line, &loc, '\n');
if (*title == '\0') {
bar_set_title(monitor->bar, "");
} else
bar_set_title(monitor->bar, title);
free(title);
} else if (STRING_EQUAL(command, "appid")) {
/* Do nothing */
} else if (STRING_EQUAL(command, "floating")) {
char *is_floating = to_delimiter(line, &loc, '\n');
if (*is_floating == '1')
bar_set_floating(monitor->bar, 1);
else
bar_set_floating(monitor->bar, 0);
free(is_floating);
} else if (STRING_EQUAL(command, "fullscreen")) {
/* Do nothing */
} else if (STRING_EQUAL(command, "selmon")) {
char *selmon = to_delimiter(line, &loc, '\n');
if (*selmon == '1')
bar_set_active(monitor->bar, 1);
else
bar_set_active(monitor->bar, 0);
free(selmon);
} else if (STRING_EQUAL(command, "tags")) {
char *occupied_str, *tags_str, *clients_str, *urgent_str;
int occupied, _tags, clients, urgent, i, tag_mask, state;
occupied_str = to_delimiter(line, &loc, ' ');
tags_str = to_delimiter(line, &loc, ' ');
clients_str = to_delimiter(line, &loc, ' ');
urgent_str = to_delimiter(line, &loc, ' ');
occupied = atoi(occupied_str);
_tags = atoi(tags_str);
clients = atoi(clients_str);
urgent = atoi(urgent_str);
for (i = 0; i < LENGTH(tags); i++) {
state = Tag_None;
tag_mask = 1 << i;
if (_tags & tag_mask)
state |= Tag_Active;
if (urgent & tag_mask)
state |= Tag_Urgent;
bar_set_tag(monitor->bar, i, state, occupied & tag_mask ? 1 : 0, clients & tag_mask ? 1 : 0);
}
free(occupied_str);
free(tags_str);
free(clients_str);
free(urgent_str);
} else if (STRING_EQUAL(command, "layout")) {
char *layout = to_delimiter(line, &loc, '\n');
bar_set_layout(monitor->bar, layout);
free(layout);
}
free(command);
monitor_update(monitor);
}
void stdin_in(int fd, short mask, void *data) {
if (mask & (POLLHUP | POLLERR)) {
running = 0;
return;
}
int new_fd = dup(fd);
FILE *stdin_file = fdopen(new_fd, "r");
char *buffer = NULL;
size_t size = 0;
while(1) {
if (getline(&buffer, &size, stdin_file) == -1)
break;
stdin_handle(buffer);
}
free(buffer);
fclose(stdin_file);
close(new_fd);
}
void sigaction_handler(int _) {
if (write(self_pipe[1], "0", 1) < 0)
panic("sigaction_handler");
}
void xdg_output_name(void *data, struct zxdg_output_v1 *output, const char *name) {
struct Monitor *monitor = data;
monitor->xdg_name = strdup(name);
zxdg_output_v1_destroy(output);
monitor->xdg_output = NULL;
}
void xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial) {
xdg_wm_base_pong(xdg_wm_base, serial);
}
void zdwl_ipc_manager_layout(void *data, struct zdwl_ipc_manager_v2 *zdwl_ipc_manager_v2, const char *name) {
layoutcount++;
}
void zdwl_ipc_manager_tags(void *data, struct zdwl_ipc_manager_v2 *zdwl_ipc_manager_v2, uint32_t amount) {
tagcount = amount;
}
void zdwl_ipc_output_active(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t active) {
struct Monitor *monitor = data;
bar_set_active(monitor->bar, active);
}
void zdwl_ipc_output_appid(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, const char *appid) {
/* Nop */
}
void zdwl_ipc_output_floating(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t is_floating) {
struct Monitor *monitor = data;
bar_set_floating(monitor->bar, is_floating);
}
void zdwl_ipc_output_frame(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2) {
struct Monitor *monitor = data;
monitor_update(monitor);
}
void zdwl_ipc_output_fullscreen(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t is_fullscreen) {
/* Nop */
}
void zdwl_ipc_output_layout(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t layout) {
struct Monitor *monitor = data;
monitor->layout = layout;
}
void zdwl_ipc_output_layout_symbol(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, const char *layout) {
struct Monitor *monitor = data;
bar_set_layout(monitor->bar, layout);
}
void zdwl_ipc_output_tag(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused) {
struct Monitor *monitor = data;
bar_set_tag(monitor->bar, tag, state, clients ? 1 : 0, focused);
monitor->tags = (state & ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE) ? monitor->tags | (1 << tag) : monitor->tags & ~(1 << tag);
}
void zdwl_ipc_output_title(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, const char *title) {
struct Monitor *monitor = data;
bar_set_title(monitor->bar, title);
}
void zdwl_ipc_output_toggle_visibility(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2) {
struct Monitor *monitor = data;
monitor->desired_visibility ^= 1;
pipeline_hide(monitor->pipeline);
monitor_update(monitor);
}
int main(int argc, char *argv[]) {
int opt;
while((opt = getopt(argc, argv, "l")) != -1) {

ファイルの表示

@ -1,7 +1,7 @@
#ifndef MAIN_H_
#define MAIN_H_
#include "xdg-output-unstable-v1-protocol.h"
#include "dwl-ipc-unstable-v2-protocol.h"
#include <stdint.h>
#include <wayland-client.h>
#include <wayland-util.h>
@ -9,11 +9,11 @@
#define VERSION 0.0
struct Monitor {
char *xdg_name;
uint32_t wl_name;
unsigned int desired_visibility, tags, layout;
struct wl_output *wl_output;
struct zxdg_output_v1 *xdg_output;
struct zdwl_ipc_output_v2 *dwl_output;
struct Pipeline *pipeline;
struct List *hotspots; /* struct Hotspot* */
struct Bar *bar;
@ -28,5 +28,6 @@ struct Monitor *monitor_from_surface(const struct wl_surface *surface);
extern struct wl_compositor *compositor;
extern struct zwlr_layer_shell_v1 *shell;
extern struct wl_shm *shm;
extern int layoutcount;
#endif // MAIN_H_

ファイルの表示

@ -134,7 +134,7 @@ void pipeline_destroy(struct Pipeline *pipeline) {
list_elements_destroy(pipeline->callbacks, free);
g_object_unref(pipeline->context);
g_object_unref(pipeline->font->description);
pango_font_description_free(pipeline->font->description);
free(pipeline->font);
shm_destroy(pipeline->shm);
wl_surface_destroy(pipeline->surface);

ファイルの表示

@ -45,9 +45,7 @@ static struct Buffer buffer_create(struct MemoryMapping *map, struct wl_shm_pool
void buffer_destroy(struct Buffer *buffer) {
if (!buffer) return;
wl_buffer_destroy(buffer->buffer);
free(buffer);
}
struct MemoryMapping memory_mapping_create(int fd, int pool_size) {
@ -67,9 +65,7 @@ struct MemoryMapping memory_mapping_create(int fd, int pool_size) {
void memory_mapping_destroy(struct MemoryMapping *map) {
if (!map) return;
munmap(map->ptr, map->size);
free(map);
}
struct Shm *shm_create(int width, int height, enum wl_shm_format format) {

ファイルの表示

@ -4,6 +4,18 @@
#include <stdio.h>
#include <stdlib.h>
void layout(struct Monitor *monitor, const union Arg *arg) {
if ((monitor->layout == 0 && !arg->ui) || (monitor->layout == layoutcount-1 && arg->ui))
return;
if (arg->ui)
monitor->layout++;
else
monitor->layout--;
zdwl_ipc_output_v2_set_layout(monitor->dwl_output, monitor->layout);
}
void spawn(struct Monitor *monitor, const union Arg *arg) {
if (fork() != 0)
return;
@ -15,3 +27,15 @@ void spawn(struct Monitor *monitor, const union Arg *arg) {
perror(" failed\n");
exit(1);
}
void tag(struct Monitor *monitor, const union Arg *arg) {
zdwl_ipc_output_v2_set_client_tags(monitor->dwl_output, 0, 1<<arg->ui);
}
void toggle_view(struct Monitor *monitor, const union Arg *arg) {
zdwl_ipc_output_v2_set_tags(monitor->dwl_output, monitor->tags ^ (1<<arg->ui), 0);
}
void view(struct Monitor *monitor, const union Arg *arg) {
zdwl_ipc_output_v2_set_tags(monitor->dwl_output, 1<<arg->ui, 1);
}

ファイルの表示

@ -46,6 +46,10 @@ struct Binding {
const union Arg arg;
};
void layout(struct Monitor *monitor, const union Arg *arg);
void spawn(struct Monitor *monitor, const union Arg *arg);
void tag(struct Monitor *monitor, const union Arg *arg);
void toggle_view(struct Monitor *monitor, const union Arg *arg);
void view(struct Monitor *monitor, const union Arg *arg);
#endif // USER_H_

ファイルの表示

@ -102,7 +102,7 @@ void list_resize(struct List *list) {
return;
list->allocated *= 2;
list->data = realloc(list->data, list->allocated);
list->data = realloc(list->data, sizeof(void*) * list->allocated);
}
char *string_create(const char *fmt, ...) {