diff options
Diffstat (limited to 'dwl.c')
-rw-r--r-- | dwl.c | 319 |
1 files changed, 185 insertions, 134 deletions
@@ -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 |