aboutsummaryrefslogtreecommitdiff
path: root/dwl.c
diff options
context:
space:
mode:
Diffstat (limited to 'dwl.c')
-rw-r--r--dwl.c319
1 files changed, 185 insertions, 134 deletions
diff --git a/dwl.c b/dwl.c
index 2128751..336c939 100644
--- a/dwl.c
+++ b/dwl.c
@@ -57,7 +57,7 @@
#define LENGTH(X) (sizeof X / sizeof X[0])
#define END(A) ((A) + LENGTH(A))
#define TAGMASK ((1 << LENGTH(tags)) - 1)
-#define ROUND(X) ((X)>=0?(long)((X)+0.5):(long)((X)-0.5))
+#define ROUND(X) ((int)((X)+0.5))
#ifdef XWAYLAND
#define WLR_SURFACE(C) ((C)->type != XDGShell ? (C)->surface.xwayland->surface : (C)->surface.xdg->surface)
#else
@@ -113,13 +113,13 @@ typedef struct {
#endif
int bw;
unsigned int tags;
- bool isfloating;
+ int isfloating;
uint32_t resize; /* configure serial of a pending resize */
- int oldx;
- int oldy;
- int oldwidth;
- int oldheight;
- bool isfullscreen;
+ int prevx;
+ int prevy;
+ int prevwidth;
+ int prevheight;
+ int isfullscreen;
} Client;
typedef struct {
@@ -175,6 +175,7 @@ struct Monitor {
unsigned int tagset[2];
double mfact;
int nmaster;
+ Client *fullscreenclient;
int position;
};
@@ -191,7 +192,7 @@ typedef struct {
const char *id;
const char *title;
unsigned int tags;
- bool isfloating;
+ int isfloating;
int monitor;
} Rule;
@@ -211,7 +212,7 @@ static void applyexclusive(struct wlr_box *usable_area, uint32_t anchor,
static void applyrules(Client *c);
static void arrange(Monitor *m);
static void arrangelayer(Monitor *m, struct wl_list *list,
- struct wlr_box *usable_area, bool exclusive);
+ struct wlr_box *usable_area, int exclusive);
static void arrangelayers(Monitor *m);
static void axisnotify(struct wl_listener *listener, void *data);
static void buttonpress(struct wl_listener *listener, void *data);
@@ -233,7 +234,7 @@ static void destroylayersurfacenotify(struct wl_listener *listener, void *data);
static void destroynotify(struct wl_listener *listener, void *data);
static void destroyxdeco(struct wl_listener *listener, void *data);
static Monitor *dirtomon(int dir);
-static void focusclient(Client *c, bool lift);
+static void focusclient(Client *c, int lift);
static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg);
static void fullscreennotify(struct wl_listener *listener, void *data);
@@ -241,19 +242,20 @@ static Client *focustop(Monitor *m);
static void getxdecomode(struct wl_listener *listener, void *data);
static void incnmaster(const Arg *arg);
static void inputdevice(struct wl_listener *listener, void *data);
-static bool keybinding(uint32_t mods, xkb_keysym_t sym);
+static int keybinding(uint32_t mods, xkb_keysym_t sym);
static void keypress(struct wl_listener *listener, void *data);
static void keypressmod(struct wl_listener *listener, void *data);
static void killclient(const Arg *arg);
static void maplayersurfacenotify(struct wl_listener *listener, void *data);
static void mapnotify(struct wl_listener *listener, void *data);
+static void maximizeclient(Client *c);
static void monocle(Monitor *m);
static void motionabsolute(struct wl_listener *listener, void *data);
static void motionnotify(uint32_t time);
static void motionrelative(struct wl_listener *listener, void *data);
static void moveresize(const Arg *arg);
static void outputmgrapply(struct wl_listener *listener, void *data);
-static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, bool test);
+static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test);
static void outputmgrtest(struct wl_listener *listener, void *data);
static void pointerfocus(Client *c, struct wlr_surface *surface,
double sx, double sy, uint32_t time);
@@ -262,15 +264,15 @@ static void render(struct wlr_surface *surface, int sx, int sy, void *data);
static void renderclients(Monitor *m, struct timespec *now);
static void renderlayer(struct wl_list *layer_surfaces, struct timespec *now);
static void rendermon(struct wl_listener *listener, void *data);
-static void resize(Client *c, int x, int y, int w, int h, bool interact);
+static void resize(Client *c, int x, int y, int w, int h, int interact);
static void run(char *startup_cmd);
static void scalebox(struct wlr_box *box, float scale);
static Client *selclient(void);
static void setcursor(struct wl_listener *listener, void *data);
static void setpsel(struct wl_listener *listener, void *data);
static void setsel(struct wl_listener *listener, void *data);
-static void setfloating(Client *c, bool floating);
-static void setfullscreen(Client *c, bool fullscreen);
+static void setfloating(Client *c, int floating);
+static void setfullscreen(Client *c, int fullscreen);
static void setlayout(const Arg *arg);
static void setmfact(const Arg *arg);
static void setmon(Client *c, Monitor *m, unsigned int newtags);
@@ -281,6 +283,7 @@ static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
static void tile(Monitor *m);
static void togglefloating(const Arg *arg);
+static void togglefullscreen(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
static void unmaplayersurface(LayerSurface *layersurface);
@@ -299,7 +302,7 @@ static void zoom(const Arg *arg);
static const char broken[] = "broken";
static struct wl_display *dpy;
static struct wlr_backend *backend;
-static struct wlr_renderer *renderer;
+static struct wlr_renderer *drw;
static struct wlr_compositor *compositor;
static struct wlr_xdg_shell *xdg_shell;
@@ -315,6 +318,10 @@ static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr;
static struct wlr_cursor *cursor;
static struct wlr_xcursor_manager *cursor_mgr;
+#ifdef XWAYLAND
+static struct wlr_xcursor *xcursor;
+static struct wlr_xcursor_manager *xcursor_mgr;
+#endif
static struct wlr_seat *seat;
static struct wl_list keyboards;
@@ -500,11 +507,13 @@ arrange(Monitor *m)
{
if (m->lt[m->sellt]->arrange)
m->lt[m->sellt]->arrange(m);
+ else if (m->fullscreenclient)
+ maximizeclient(m->fullscreenclient);
/* TODO recheck pointer focus here... or in resize()? */
}
void
-arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, bool exclusive)
+arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, int exclusive)
{
LayerSurface *layersurface;
struct wlr_box full_area = m->m;
@@ -586,13 +595,13 @@ arrangelayers(Monitor *m)
// Arrange exclusive surfaces from top->bottom
arrangelayer(m, &m->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
- &usable_area, true);
+ &usable_area, 1);
arrangelayer(m, &m->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
- &usable_area, true);
+ &usable_area, 1);
arrangelayer(m, &m->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
- &usable_area, true);
+ &usable_area, 1);
arrangelayer(m, &m->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
- &usable_area, true);
+ &usable_area, 1);
if (memcmp(&usable_area, &m->w, sizeof(struct wlr_box))) {
m->w = usable_area;
@@ -601,13 +610,13 @@ arrangelayers(Monitor *m)
// Arrange non-exlusive surfaces from top->bottom
arrangelayer(m, &m->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
- &usable_area, false);
+ &usable_area, 0);
arrangelayer(m, &m->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
- &usable_area, false);
+ &usable_area, 0);
arrangelayer(m, &m->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
- &usable_area, false);
+ &usable_area, 0);
arrangelayer(m, &m->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
- &usable_area, false);
+ &usable_area, 0);
// Find topmost keyboard interactive layer, if such a layer exists
uint32_t layers_above_shell[] = {
@@ -623,7 +632,7 @@ arrangelayers(Monitor *m)
if (layersurface->layer_surface->current.keyboard_interactive &&
layersurface->layer_surface->mapped) {
// Deactivate the focused client.
- focusclient(NULL, false);
+ focusclient(NULL, 0);
wlr_seat_keyboard_notify_enter(seat, layersurface->layer_surface->surface,
kb->keycodes, kb->num_keycodes, &kb->modifiers);
return;
@@ -657,7 +666,7 @@ buttonpress(struct wl_listener *listener, void *data)
/* Change focus if the button was _pressed_ over a client */
Client *c;
if ((c = xytoclient(cursor->x, cursor->y)))
- focusclient(c, true);
+ focusclient(c, 1);
struct wlr_keyboard* keyboard = wlr_seat_get_keyboard(seat);
uint32_t mods = wlr_keyboard_get_modifiers(keyboard);
@@ -739,7 +748,7 @@ cleanupmon(struct wl_listener *listener, void *data)
do // don't switch to disabled mons
selmon = wl_container_of(mons.prev, selmon, link);
while (!selmon->wlr_output->enabled && i++ < nmons);
- focusclient(focustop(selmon), true);
+ focusclient(focustop(selmon), 1);
closemon(m);
free(m);
}
@@ -753,7 +762,7 @@ closemon(Monitor *m)
wl_list_for_each(c, &clients, link) {
if (c->isfloating && c->geom.x > m->m.width)
resize(c, c->geom.x - m->w.width, c->geom.y,
- c->geom.width, c->geom.height, false);
+ c->geom.width, c->geom.height, 0);
if (c->mon == m)
setmon(c, selmon, c->tags);
}
@@ -851,7 +860,7 @@ createmon(struct wl_listener *listener, void *data)
break;
}
}
- wlr_output_enable_adaptive_sync(wlr_output, true);
+ wlr_output_enable_adaptive_sync(wlr_output, 1);
/* Set up event listeners */
m->frame.notify = rendermon;
wl_signal_add(&wlr_output->events.frame, &m->frame);
@@ -870,7 +879,7 @@ createmon(struct wl_listener *listener, void *data)
wl_list_insert(&mons, &m->link);
}
- wlr_output_enable(wlr_output, true);
+ wlr_output_enable(wlr_output, 1);
if (!wlr_output_commit(wlr_output))
return;
@@ -901,7 +910,7 @@ createmon(struct wl_listener *listener, void *data)
wl_list_for_each(c, &clients, link) {
if (c->isfloating)
resize(c, c->geom.x + m->w.width, c->geom.y,
- c->geom.width, c->geom.height, false);
+ c->geom.width, c->geom.height, 0);
}
return;
}
@@ -919,7 +928,7 @@ createnotify(struct wl_listener *listener, void *data)
return;
wl_list_for_each(c, &clients, link)
if (c->isfullscreen && VISIBLEON(c, c->mon))
- setfullscreen(c, false);
+ setfullscreen(c, 0);
/* Allocate a Client for this surface */
c = xdg_surface->data = calloc(1, sizeof(*c));
@@ -942,7 +951,7 @@ createnotify(struct wl_listener *listener, void *data)
c->fullscreen.notify = fullscreennotify;
wl_signal_add(&xdg_surface->toplevel->events.request_fullscreen, &c->fullscreen);
- c->isfullscreen = false;
+ c->isfullscreen = 0;
}
void
@@ -985,14 +994,16 @@ createlayersurface(struct wl_listener *listener, void *data)
void
createpointer(struct wlr_input_device *device)
{
- struct libinput_device *libinput_device = (struct libinput_device*)
+ if (wlr_input_device_is_libinput(device)) {
+ struct libinput_device *libinput_device = (struct libinput_device*)
wlr_libinput_get_device_handle(device);
- if (tap_to_click && libinput_device_config_tap_get_finger_count(libinput_device))
- libinput_device_config_tap_set_enabled(libinput_device, LIBINPUT_CONFIG_TAP_ENABLED);
+ if (tap_to_click && libinput_device_config_tap_get_finger_count(libinput_device))
+ libinput_device_config_tap_set_enabled(libinput_device, LIBINPUT_CONFIG_TAP_ENABLED);
- if (libinput_device_config_scroll_has_natural_scroll(libinput_device))
- libinput_device_config_scroll_set_natural_scroll_enabled(libinput_device, natural_scrolling);
+ if (libinput_device_config_scroll_has_natural_scroll(libinput_device))
+ libinput_device_config_scroll_set_natural_scroll_enabled(libinput_device, natural_scrolling);
+ }
/* We don't do anything special with pointers. All of our pointer handling
* is proxied through wlr_cursor. On another compositor, you might take this
@@ -1077,7 +1088,21 @@ destroyxdeco(struct wl_listener *listener, void *data)
}
void
-setfullscreen(Client *c, bool fullscreen)
+togglefullscreen(const Arg *arg)
+{
+ Client *sel = selclient();
+ setfullscreen(sel, !sel->isfullscreen);
+}
+
+void
+maximizeclient(Client *c)
+{
+ resize(c, c->mon->m.x, c->mon->m.y, c->mon->m.width, c->mon->m.height, 0);
+ /* used for fullscreen clients */
+}
+
+void
+setfullscreen(Client *c, int fullscreen)
{
c->isfullscreen = fullscreen;
c->bw = (1 - fullscreen) * borderpx;
@@ -1089,16 +1114,19 @@ setfullscreen(Client *c, bool fullscreen)
#endif
wlr_xdg_toplevel_set_fullscreen(c->surface.xdg, fullscreen);
- // restore previous size instead of arrange to work with floating windows
if (fullscreen) {
- c->oldx = c->geom.x;
- c->oldy = c->geom.y;
- c->oldheight = c->geom.height;
- c->oldwidth = c->geom.width;
- resize(c, c->mon->m.x, c->mon->m.y,
- c->mon->m.width, c->mon->m.height, false);
+ c->prevx = c->geom.x;
+ c->prevy = c->geom.y;
+ c->prevheight = c->geom.height;
+ c->prevwidth = c->geom.width;
+ c->mon->fullscreenclient = c;
+ maximizeclient(c);
} else {
- resize(c, c->oldx, c->oldy, c->oldwidth, c->oldheight, false);
+ /* restore previous size instead of arrange for floating windows since
+ * client positions are set by the user and cannot be recalculated */
+ resize(c, c->prevx, c->prevy, c->prevwidth, c->prevheight, 0);
+ c->mon->fullscreenclient = NULL;
+ arrange(c->mon);
}
}
@@ -1126,7 +1154,7 @@ dirtomon(int dir)
}
void
-focusclient(Client *c, bool lift)
+focusclient(Client *c, int lift)
{
/* Raise client in stacking order if requested */
if (c && lift) {
@@ -1150,11 +1178,11 @@ focusclient(Client *c, bool lift)
if (old && (!c || WLR_SURFACE(c) != old)) {
if (wlr_surface_is_xdg_surface(old))
wlr_xdg_toplevel_set_activated(
- wlr_xdg_surface_from_wlr_surface(old), false);
+ wlr_xdg_surface_from_wlr_surface(old), 0);
#ifdef XWAYLAND
else if (wlr_surface_is_xwayland_surface(old))
wlr_xwayland_surface_activate(
- wlr_xwayland_surface_from_wlr_surface(old), false);
+ wlr_xwayland_surface_from_wlr_surface(old), 0);
#endif
/* If an overlay is focused, don't focus or activate the client,
* but only update its position in fstack to render its border with focuscolor
@@ -1187,10 +1215,10 @@ focusclient(Client *c, bool lift)
/* Activate the new client */
#ifdef XWAYLAND
if (c->type != XDGShell)
- wlr_xwayland_surface_activate(c->surface.xwayland, true);
+ wlr_xwayland_surface_activate(c->surface.xwayland, 1);
else
#endif
- wlr_xdg_toplevel_set_activated(c->surface.xdg, true);
+ wlr_xdg_toplevel_set_activated(c->surface.xdg, 1);
}
void
@@ -1199,7 +1227,7 @@ focusmon(const Arg *arg)
do
selmon = dirtomon(arg->i);
while (!selmon->wlr_output->enabled);
- focusclient(focustop(selmon), true);
+ focusclient(focustop(selmon), 1);
}
void
@@ -1225,7 +1253,7 @@ focusstack(const Arg *arg)
}
}
/* If only one client is visible on selmon, then c == sel */
- focusclient(c, true);
+ focusclient(c, 1);
}
Client *
@@ -1280,7 +1308,7 @@ inputdevice(struct wl_listener *listener, void *data)
wlr_seat_set_capabilities(seat, caps);
}
-bool
+int
keybinding(uint32_t mods, xkb_keysym_t sym)
{
/*
@@ -1288,13 +1316,13 @@ keybinding(uint32_t mods, xkb_keysym_t sym)
* processing keys, rather than passing them on to the client for its own
* processing.
*/
- bool handled = false;
+ int handled = 0;
const Key *k;
for (k = keys; k < END(keys); k++) {
if (CLEANMASK(mods) == CLEANMASK(k->mod) &&
sym == k->keysym && k->func) {
k->func(&k->arg);
- handled = true;
+ handled = 1;
}
}
return handled;
@@ -1303,6 +1331,7 @@ keybinding(uint32_t mods, xkb_keysym_t sym)
void
keypress(struct wl_listener *listener, void *data)
{
+ int i;
/* This event is raised when a key is pressed or released. */
Keyboard *kb = wl_container_of(listener, kb, key);
struct wlr_event_keyboard_key *event = data;
@@ -1314,14 +1343,14 @@ keypress(struct wl_listener *listener, void *data)
int nsyms = xkb_state_key_get_syms(
kb->device->keyboard->xkb_state, keycode, &syms);
- bool handled = false;
+ int handled = 0;
uint32_t mods = wlr_keyboard_get_modifiers(kb->device->keyboard);
wlr_idle_notify_activity(idle, seat);
/* On _press_, attempt to process a compositor keybinding. */
- if (event->state == WLR_KEY_PRESSED)
- for (int i = 0; i < nsyms; i++)
+ if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED)
+ for (i = 0; i < nsyms; i++)
handled = keybinding(mods, syms[i]) || handled;
if (!handled) {
@@ -1377,7 +1406,7 @@ void
mapnotify(struct wl_listener *listener, void *data)
{
/* Called when the surface is mapped, or ready to display on-screen. */
- Client *c = wl_container_of(listener, c, map);
+ Client *c = wl_container_of(listener, c, map), *oldfocus = selclient();
#ifdef XWAYLAND
if (c->type == X11Unmanaged) {
@@ -1408,6 +1437,14 @@ mapnotify(struct wl_listener *listener, void *data)
/* Set initial monitor, tags, floating status, and focus */
applyrules(c);
+
+ if (c->mon->fullscreenclient && c->mon->fullscreenclient == oldfocus
+ && !c->isfloating && c->mon->lt[c->mon->sellt]->arrange) {
+ maximizeclient(c->mon->fullscreenclient);
+ focusclient(c->mon->fullscreenclient, 1);
+ /* give the focus back the fullscreen client on that monitor if exists,
+ * is focused and the new client isn't floating */
+ }
}
void
@@ -1418,11 +1455,10 @@ monocle(Monitor *m)
wl_list_for_each(c, &clients, link) {
if (!VISIBLEON(c, m) || c->isfloating)
continue;
- if (c->isfullscreen) {
- resize(c, c->mon->m.x, c->mon->m.y, c->mon->m.width, c->mon->m.height, false);
- return;
- }
- resize(c, m->w.x, m->w.y, m->w.width, m->w.height, false);
+ if (c->isfullscreen)
+ maximizeclient(c);
+ else
+ resize(c, m->w.x, m->w.y, m->w.width, m->w.height, 0);
}
}
@@ -1456,12 +1492,12 @@ motionnotify(uint32_t time)
if (cursor_mode == CurMove) {
/* Move the grabbed client to the new position. */
resize(grabc, cursor->x - grabcx, cursor->y - grabcy,
- grabc->geom.width, grabc->geom.height, true);
+ grabc->geom.width, grabc->geom.height, 1);
return;
} else if (cursor_mode == CurResize) {
resize(grabc, grabc->geom.x, grabc->geom.y,
cursor->x - grabc->geom.x,
- cursor->y - grabc->geom.y, true);
+ cursor->y - grabc->geom.y, 1);
return;
}
@@ -1537,7 +1573,7 @@ moveresize(const Arg *arg)
return;
/* Float the window and tell motionnotify to grab it */
- setfloating(grabc, true);
+ setfloating(grabc, 1);
switch (cursor_mode = arg->ui) {
case CurMove:
grabcx = cursor->x - grabc->geom.x;
@@ -1560,14 +1596,14 @@ void
outputmgrapply(struct wl_listener *listener, void *data)
{
struct wlr_output_configuration_v1 *config = data;
- outputmgrapplyortest(config, false);
+ outputmgrapplyortest(config, 0);
}
void
-outputmgrapplyortest(struct wlr_output_configuration_v1 *config, bool test)
+outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test)
{
struct wlr_output_configuration_head_v1 *config_head;
- bool ok = true;
+ int ok = 1;
wl_list_for_each(config_head, &config->heads, link) {
struct wlr_output *wlr_output = config_head->state.output;
@@ -1619,7 +1655,7 @@ void
outputmgrtest(struct wl_listener *listener, void *data)
{
struct wlr_output_configuration_v1 *config = data;
- outputmgrapplyortest(config, true);
+ outputmgrapplyortest(config, 1);
}
void
@@ -1636,7 +1672,7 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
return;
}
- bool internal_call = !time;
+ int internal_call = !time;
if (!time) {
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
@@ -1662,7 +1698,7 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
#endif
if (sloppyfocus && !internal_call)
- focusclient(c, false);
+ focusclient(c, 0);
}
void
@@ -1723,7 +1759,7 @@ render(struct wlr_surface *surface, int sx, int sy, void *data)
/* This takes our matrix, the texture, and an alpha, and performs the actual
* rendering on the GPU. */
- wlr_render_texture_with_matrix(renderer, texture, matrix, 1);
+ wlr_render_texture_with_matrix(drw, texture, matrix, 1);
/* This lets the client know that we've displayed that frame and it can
* prepare another one now if it likes. */
@@ -1734,6 +1770,12 @@ void
renderclients(Monitor *m, struct timespec *now)
{
Client *c, *sel = selclient();
+ const float *color;
+ double ox, oy;
+ int i, w, h;
+ struct render_data rdata;
+ struct wlr_box *borders;
+ struct wlr_surface *surface;
/* Each subsequent window we render is rendered on top of the last. Because
* our stacking list is ordered front-to-back, we iterate over it backwards. */
wl_list_for_each_reverse(c, &stack, slink) {
@@ -1742,36 +1784,36 @@ renderclients(Monitor *m, struct timespec *now)
output_layout, m->wlr_output, &c->geom))
continue;
- struct wlr_surface *surface = WLR_SURFACE(c);
- double ox = c->geom.x, oy = c->geom.y;
+ surface = WLR_SURFACE(c);
+ ox = c->geom.x, oy = c->geom.y;
wlr_output_layout_output_coords(output_layout, m->wlr_output,
&ox, &oy);
- int w = surface->current.width;
- int h = surface->current.height;
- struct wlr_box *borders = (struct wlr_box[4]) {
- {ox, oy, w + 2 * c->bw, c->bw}, /* top */
- {ox, oy + c->bw, c->bw, h}, /* left */
- {ox + c->bw + w, oy + c->bw, c->bw, h}, /* right */
- {ox, oy + c->bw + h, w + 2 * c->bw, c->bw}, /* bottom */
- };
-
- /* Draw window borders */
- const float *color = (c == sel) ? focuscolor : bordercolor;
- for (int i = 0; i < 4; i++) {
- scalebox(&borders[i], m->wlr_output->scale);
- wlr_render_rect(renderer, &borders[i], color,
- m->wlr_output->transform_matrix);
+ if (c->bw) {
+ w = surface->current.width;
+ h = surface->current.height;
+ borders = (struct wlr_box[4]) {
+ {ox, oy, w + 2 * c->bw, c->bw}, /* top */
+ {ox, oy + c->bw, c->bw, h}, /* left */
+ {ox + c->bw + w, oy + c->bw, c->bw, h}, /* right */
+ {ox, oy + c->bw + h, w + 2 * c->bw, c->bw}, /* bottom */
+ };
+
+ /* Draw window borders */
+ color = (c == sel) ? focuscolor : bordercolor;
+ for (i = 0; i < 4; i++) {
+ scalebox(&borders[i], m->wlr_output->scale);
+ wlr_render_rect(drw, &borders[i], color,
+ m->wlr_output->transform_matrix);
+ }
}
/* This calls our render function for each surface among the
* xdg_surface's toplevel and popups. */
- struct render_data rdata = {
- .output = m->wlr_output,
- .when = now,
- .x = c->geom.x + c->bw,
- .y = c->geom.y + c->bw,
- };
+ rdata.output = m->wlr_output;
+ rdata.when = now;
+ rdata.x = c->geom.x + c->bw;
+ rdata.y = c->geom.y + c->bw;
#ifdef XWAYLAND
if (c->type != XDGShell)
wlr_surface_for_each_surface(c->surface.xwayland->surface, render, &rdata);
@@ -1810,11 +1852,11 @@ rendermon(struct wl_listener *listener, void *data)
/* Do not render if any XDG clients have an outstanding resize. */
Client *c;
- bool render = true;
+ int render = 1;
wl_list_for_each(c, &stack, slink) {
if (c->resize) {
wlr_surface_send_frame_done(WLR_SURFACE(c), &now);
- render = false;
+ render = 0;
}
}
@@ -1824,8 +1866,8 @@ rendermon(struct wl_listener *listener, void *data)
if (render) {
/* Begin the renderer (calls glViewport and some other GL sanity checks) */
- wlr_renderer_begin(renderer, m->wlr_output->width, m->wlr_output->height);
- wlr_renderer_clear(renderer, rootcolor);
+ wlr_renderer_begin(drw, m->wlr_output->width, m->wlr_output->height);
+ wlr_renderer_clear(drw, rootcolor);
renderlayer(&m->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &now);
renderlayer(&m->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &now);
@@ -1846,14 +1888,14 @@ rendermon(struct wl_listener *listener, void *data)
/* Conclude rendering and swap the buffers, showing the final frame
* on-screen. */
- wlr_renderer_end(renderer);
+ wlr_renderer_end(drw);
}
wlr_output_commit(m->wlr_output);
}
void
-resize(Client *c, int x, int y, int w, int h, bool interact)
+resize(Client *c, int x, int y, int w, int h, int interact)
{
/*
* Note that I took some shortcuts here. In a more fleshed-out
@@ -1967,10 +2009,8 @@ setcursor(struct wl_listener *listener, void *data)
}
void
-setfloating(Client *c, bool floating)
+setfloating(Client *c, int floating)
{
- if (c->isfloating == floating)
- return;
c->isfloating = floating;
arrange(c->mon);
}
@@ -2020,7 +2060,7 @@ setmon(Client *c, Monitor *m, unsigned int newtags)
c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */
arrange(m);
}
- focusclient(focustop(selmon), true);
+ focusclient(focustop(selmon), 1);
}
void
@@ -2069,8 +2109,8 @@ setup(void)
/* If we don't provide a renderer, autocreate makes a GLES2 renderer for us.
* The renderer is responsible for defining the various pixel formats it
* supports for shared memory, this configures that for clients. */
- renderer = wlr_backend_get_renderer(backend);
- wlr_renderer_init_wl_display(renderer, dpy);
+ drw = wlr_backend_get_renderer(backend);
+ wlr_renderer_init_wl_display(drw, dpy);
/* This creates some hands-off wlroots interfaces. The compositor is
* necessary for clients to allocate surfaces and the data device manager
@@ -2078,7 +2118,7 @@ setup(void)
* to dig your fingers in and play with their behavior if you want. Note that
* the clients cannot set the selection directly without compositor approval,
* see the setsel() function. */
- compositor = wlr_compositor_create(dpy, renderer);
+ compositor = wlr_compositor_create(dpy, drw);
wlr_export_dmabuf_manager_v1_create(dpy);
wlr_screencopy_manager_v1_create(dpy);
wlr_data_control_manager_v1_create(dpy);
@@ -2180,12 +2220,26 @@ setup(void)
* Initialise the XWayland X server.
* It will be started when the first X client is started.
*/
- xwayland = wlr_xwayland_create(dpy, compositor, true);
+ xwayland = wlr_xwayland_create(dpy, compositor, 1);
if (xwayland) {
wl_signal_add(&xwayland->events.ready, &xwayland_ready);
wl_signal_add(&xwayland->events.new_surface, &new_xwayland_surface);
- setenv("DISPLAY", xwayland->display_name, true);
+ /*
+ * Create the XWayland cursor manager at scale 1, setting its default
+ * pointer to match the rest of dwl.
+ */
+ xcursor_mgr = wlr_xcursor_manager_create(NULL, 24);
+ wlr_xcursor_manager_load(xcursor_mgr, 1);
+ xcursor = wlr_xcursor_manager_get_xcursor(xcursor_mgr, "left_ptr", 1);
+ if (xcursor) {
+ wlr_xwayland_set_cursor(xwayland,
+ xcursor->images[0]->buffer, xcursor->images[0]->width * 4,
+ xcursor->images[0]->width, xcursor->images[0]->height,
+ xcursor->images[0]->hotspot_x, xcursor->images[0]->hotspot_y);
+ }
+
+ setenv("DISPLAY", xwayland->display_name, 1);
} else {
fprintf(stderr, "failed to setup XWayland X server, continuing without it\n");
}
@@ -2217,7 +2271,7 @@ tag(const Arg *arg)
Client *sel = selclient();
if (sel && arg->ui & TAGMASK) {
sel->tags = arg->ui & TAGMASK;
- focusclient(focustop(selmon), true);
+ focusclient(focustop(selmon), 1);
arrange(selmon);
}
}
@@ -2251,18 +2305,15 @@ tile(Monitor *m)
wl_list_for_each(c, &clients, link) {
if (!VISIBLEON(c, m) || c->isfloating)
continue;
- if (c->isfullscreen) {
- resize(c, c->mon->m.x, c->mon->m.y,
- c->mon->m.width, c->mon->m.height, false);
- return;
- }
- if (i < m->nmaster) {
+ if (c->isfullscreen)
+ maximizeclient(c);
+ else if (i < m->nmaster) {
h = (m->w.height - my) / (MIN(n, m->nmaster) - i);
- resize(c, m->w.x, m->w.y + my, mw, h, false);
+ resize(c, m->w.x, m->w.y + my, mw, h, 0);
my += c->geom.height;
} else {
h = (m->w.height - ty) / (n - i);
- resize(c, m->w.x + mw, m->w.y + ty, m->w.width - mw, h, false);
+ resize(c, m->w.x + mw, m->w.y + ty, m->w.width - mw, h, 0);
ty += c->geom.height;
}
i++;
@@ -2288,7 +2339,7 @@ toggletag(const Arg *arg)
unsigned int newtags = sel->tags ^ (arg->ui & TAGMASK);
if (newtags) {
sel->tags = newtags;
- focusclient(focustop(selmon), true);
+ focusclient(focustop(selmon), 1);
arrange(selmon);
}
}
@@ -2300,7 +2351,7 @@ toggleview(const Arg *arg)
if (newtagset) {
selmon->tagset[selmon->seltags] = newtagset;
- focusclient(focustop(selmon), true);
+ focusclient(focustop(selmon), 1);
arrange(selmon);
}
}
@@ -2308,10 +2359,10 @@ toggleview(const Arg *arg)
void
unmaplayersurface(LayerSurface *layersurface)
{
- layersurface->layer_surface->mapped = false;
+ layersurface->layer_surface->mapped = 0;
if (layersurface->layer_surface->surface ==
seat->keyboard_state.focused_surface)
- focusclient(selclient(), true);
+ focusclient(selclient(), 1);
motionnotify(0);
}
@@ -2372,7 +2423,7 @@ view(const Arg *arg)
selmon->seltags ^= 1; /* toggle sel tagset */
if (arg->ui & TAGMASK)
selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
- focusclient(focustop(selmon), true);
+ focusclient(focustop(selmon), 1);
arrange(selmon);
}
@@ -2452,7 +2503,7 @@ zoom(const Arg *arg)
wl_list_remove(&sel->link);
wl_list_insert(&clients, &sel->link);
- focusclient(sel, true);
+ focusclient(sel, 1);
arrange(selmon);
}
@@ -2464,7 +2515,7 @@ activatex11(struct wl_listener *listener, void *data)
/* Only "managed" windows can be activated */
if (c->type == X11Managed)
- wlr_xwayland_surface_activate(c->surface.xwayland, true);
+ wlr_xwayland_surface_activate(c->surface.xwayland, 1);
}
void
@@ -2482,7 +2533,7 @@ createnotifyx11(struct wl_listener *listener, void *data)
Client *c;
wl_list_for_each(c, &clients, link)
if (c->isfullscreen && VISIBLEON(c, c->mon))
- setfullscreen(c, false);
+ setfullscreen(c, 0);
/* Allocate a Client for this surface */
struct wlr_xwayland_surface *xwayland_surface = data;
@@ -2505,7 +2556,7 @@ createnotifyx11(struct wl_listener *listener, void *data)
c->fullscreen.notify = fullscreennotify;
wl_signal_add(&xwayland_surface->events.request_fullscreen, &c->fullscreen);
- c->isfullscreen = false;
+ c->isfullscreen = 0;
}
Atom
@@ -2557,7 +2608,7 @@ updatewindowtype(Client *c)
c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeSplash] ||
c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeToolbar] ||
c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeUtility])
- c->isfloating = true;
+ c->isfloating = 1;
}
void