+++ /dev/null
-
- ┌──────────────────────────────┐
- │ Release notes for i3 v4.8 │
- └──────────────────────────────┘
-
-This is i3 v4.8. This version is considered stable. All users of i3 are
-strongly encouraged to upgrade.
-
-The biggest new feature certainly is layout saving/restoring. See
-http://i3wm.org/docs/layout-saving.html for more details. tl;dr: export your
-current layout as JSON file, load it into new i3 sessions, get placeholder
-windows that will be replaced by the actual apps once you start them.
-
-Also very important for owners of HiDPI/“retina” displays is that i3 will now
-respect your configured DPI and scale up its UI elements accordingly. Use
-“xrandr --dpi 184” to set your dpi to 184, in case your setup does not figure
-it out automatically. To get properly scaling fonts, we also changed the
-default font from a bitmap font to a pango font (“DejaVu Sans Mono 8”).
-
-Multiple changes improve the compatibility of i3 with other software, e.g.
-java-based software (focus handling, once again) or external pagers (we now
-provide _NET_CLIENT_LIST and let pager applications change workspaces).
-
-For packagers, another change is that yajl ≥ 2.0 is now required for compiling
-i3. This should not be a problem for anyone, as that version is pretty old by
-now.
-
-For contributors, note that we have starting formatting the source code with
-clang-format-3.5. This means that there will no longer be a need to argue about
-coding style when discussing patches :).
-
- ┌────────────────────────────┐
- │ Changes in v4.8 │
- └────────────────────────────┘
-
- • docs/ipc: reformat/update list of ipc libraries
- • docs/ipc: fix current_workspace outputs reply member
- • docs/ipc: update ipc COMMAND reply docs
- • docs/userguide: fix multiple typos
- • docs/debugging: use bzip2
- • docs/debugging: explain how to enable logging on the fly
- • docs/debugging: merge the debug symbols/backtrace section
- • docs/debugging: recommend i3 --moreversion
- • man/i3-nagbar.man: update manpage to document all options
- • i3bar: Amend status line error 127 message
- • i3bar: don’t kill watcher on EOF, leads to better error messages
- • i3bar: send mouse wheel events to child too
- • i3bar: do click handling and tray padding retina-correctly
- • i3bar: render separators render-correctly
- • i3bar: reinit colors on barconfig update
- • i3bar: Don't start child unless status_command
- • i3bar: implement custom workspace numbers config
- • resize floating windows when right-clicking the decoration
- • enable shmlog when invoked as i3-with-shmlog
- • Disable pointer warps when focus_follows_mouse is disabled
- • Movement into a branch considers movement direction
- • set ewmh desktop properties on startup
- • handle ButtonPress events with child != XCB_NONE
- • implement layout restoring
- • only LOG() the DPI when it changes, DLOG() it otherwise
- • send IPC window events for focus and title changes
- • these types of windows are now floating by default:
- dialog, utility, toolbar and splash windows, modal windows, windows with an
- equal minimum and maximum size
- • send last event timestamp with WM_TAKE_FOCUS message
- • maintain the _NET_CLIENT_LIST property
- • don’t set input focus _and_ send WM_TAKE_FOCUS
- • respect CFLAGS in linking command
- • fix parallel make
- • reset SIGPIPE handler before executing a command
- • render default window border width retina-correctly
- • draw workspace buttons and padded text blocks retina-correctly
- • render resize windows retina-correctly
- • delegate click handling to dock clients
- • send complete config on barconfig_update
- • implement the window::fullscreen_mode ipc event
- • make all workspaces starting with "__" internal
- • improve error messages for i3-internal workspace names
- • allow _NET_ACTIVE_WINDOW requests to switch workspaces if they indicate
- that they are a pager (following the spec)
- • workspace assignments by number
- • add configuration option for disabling mouse warping
- • set _NET_ACTIVE_WINDOW to None when none has focus
- • set X-LightDM-DesktopName in i3.xsession.desktop to fix autostart on Ubuntu
- • don’t ELOG ipc EOF
- • replace all printf()s with D?LOG
- • delete ipc socket when exiting, cleanup tmpdir
- • default config: switch to DejaVu Sans Mono 8 as default font
- • cleanup tmpdir when restarting and not using XDG_RUNTIME_DIR
- • Snap pointer to resize bar on drag resize
- • Size resizebar according to container size
- • Fix clang -Wextra except -Wunused-parameter
- • Respect Motif hint for window decorations
-
- ┌────────────────────────────┐
- │ Bugfixes │
- └────────────────────────────┘
-
- • create con pixmaps when not needed
- • i3bar: fix resource leak: statusline_ctx needs to be freed first
- • tree_split should not split floating cons
- • fix memory leak with ipc_receive_message
- • fix invalid reads by setting con->window to NULL in tree_close
- • fix memory leak when closing windows
- • fix memory leak when matching window by criteria
- • fix memory leak when matching window by con_id
- • ignore dock clients in the resize command
- • clear wm_size_hints if they are not set
- • resize window check should check for NULL
- • fix window event crash with no window
- • i3-dmenu-desktop: also quote the %c field code
- • new_window and new_float can now be used simultaneously with different
- border widths
- • fix crash when using multiple for_window statements that move windows
- • Set input focus with last timestamp
- • handle windows whose WM_TRANSIENT_FOR points to themselve
- • don’t overwrite the original size of floating windows when changing border
- • don’t errnously render floating fullscreen windows during restart
- • ensure floating windows don’t drop out of fullscreen when restarting
- • don’t overwrite the window’s geometry after restartingnext
- • i3bar: Set `mapped` flag on trayclient creation
- • i3bar: don't show "EOF" status line error
-
- ┌────────────────────────────┐
- │ Thanks! │
- └────────────────────────────┘
-
-Thanks for testing, bugfixes, discussions and everything I forgot go out to:
-
-Aleksi Blinnikka, Alexander Berntsen, Alexander Kedrik, Antonio, Arun
-Persaud, Atte Peltomaki, bo, Campbell Barton, chris, David Coppa, eeemsi,
-Holger Langenau, Jean-Philippe Ouellet, Jens, jeroentbt, Jonas Maaskola,
-Julian Ospald, Kernc, Koston, lasers, lkraav, Marcin, Marco Hunsicker,
-Marcus Crestani, Matthias Thubauville, Maxime, Michael Stapelberg, Peter
-Boström, Petr Písař, Quentin Glidic, Steve Jones, TonyC, Tony Crisci,
-Vivien Didelot, Wieland Hoffmann, x33a, xeen
-
--- Michael Stapelberg, 2014-06-15
--- /dev/null
+
+ ┌──────────────────────────────┐
+ │ Release notes for i3 v4.9.1 │
+ └──────────────────────────────┘
+
+This is i3 v4.9.1. This version is considered stable. All users of i3 are
+strongly encouraged to upgrade.
+
+This is a bugfix release for i3 v4.9.
+
+ ┌────────────────────────────┐
+ │ Bugfixes │
+ └────────────────────────────┘
+
+ • i3bar: fix incorrect y-offset for text
+ • fix key bindings on big-endian platforms
+ • fix key bindings using Mode_switch
+ • fix keyboard layout change detection
+ • revert "Handle WM_CHANGE_STATE requests for iconic state" (fixes problems
+ with application windows disappearing, like SDL-based games when switching
+ workspaces)
+ • insert id-based match at HEAD, not TAIL (fixes window swallowing not
+ working when the criteria match the placeholder window)
+ • improve error messages on failing commands
+ • replace ~ in filepath when calling append_layout
+ • properly error out when the layout file cannot be read
+
+ ┌────────────────────────────┐
+ │ Thanks! │
+ └────────────────────────────┘
+
+Thanks for testing, bugfixes, discussions and everything I forgot go out to:
+
+ Steven McDonald, Ton van den Heuvel, Ingo Bürk
+
+-- Michael Stapelberg, 2015-03-07
-i3-wm (4.8.1-1) unstable; urgency=medium
+i3-wm (4.9.2-1) experimental; urgency=medium
- * NOT YET RELEASED
+ * NOT YET RELEASED.
- -- Michael Stapelberg <stapelberg@debian.org> Sun, 15 Jun 2014 19:37:32 +0200
+ -- Michael Stapelberg <stapelberg@debian.org> Sat, 07 Mar 2015 20:31:31 +0100
+
+i3-wm (4.9.1-1) experimental; urgency=medium
+
+ * New upstream release.
+
+ -- Michael Stapelberg <stapelberg@debian.org> Sat, 07 Mar 2015 20:01:46 +0100
+
+i3-wm (4.9-1) experimental; urgency=medium
+
+ * New upstream release.
+
+ -- Michael Stapelberg <stapelberg@debian.org> Sat, 28 Feb 2015 14:53:34 +0100
i3-wm (4.8-2) unstable; urgency=medium
Imagine for example using dmenu: The user starts dmenu by pressing Mod+d, dmenu
gets started with PID 3390. The user then decides to launch Firefox, which
-takes a long time. So he enters firefox into dmenu and presses enter. Firefox
+takes a long time. So they enter firefox into dmenu and press enter. Firefox
gets started with PID 4001. When it finally finishes loading, it creates an X11
window and uses MapWindow to make it visible. This is the first time i3
actually gets in touch with Firefox. It decides to map the window, but it has
full_text::
The most simple block you can think of is one which just includes the
only required key, the +full_text+ key. i3bar will display the string
- value and that’s it.
+ value parsed as
+ https://developer.gnome.org/pango/stable/PangoMarkupFormat.html[Pango markup].
short_text::
Where appropriate, the +short_text+ (string) entry should also be
provided. It will be used in case the status line needs to be shortened
always be found under the symlink +latest/+. Unless told differently, it will
run the tests on a separate X server instance (using Xephyr).
+Xephyr will open a window where you can inspect the running test. You can run
+the tests without an X session with Xvfb, such as with +xvfb-run
+./complete-run+. This will also speed up the tests signficantly especially on
+machines without a powerful video card.
+
.Example invocation of complete-run.pl+
---------------------------------------
$ cd ~/i3/testcases
See <<move_to_outputs>> for how to move a container/workspace to a different
RandR output.
+Workspace names are parsed as
+https://developer.gnome.org/pango/stable/PangoMarkupFormat.html[Pango markup]
+by i3bar.
+
[[back_and_forth]]
To switch back to the previously focused workspace, use +workspace
back_and_forth+; likewise, you can move containers to the previously focused
-------------------------
bindsym $mod+1 workspace 1
bindsym $mod+2 workspace 2
+bindsym $mod+3 workspace 3:<span foreground="red">vim</span>
...
bindsym $mod+Shift+1 move container to workspace 1
static int handle_expose() {
/* re-draw the background */
xcb_rectangle_t border = {0, 0, 300, (15 * font.height) + 8};
- xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {get_colorpixel("#000000")});
+ xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){get_colorpixel("#000000")});
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &border);
set_font(&font);
XCB_WINDOW_CLASS_INPUT_OUTPUT,
XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
- (uint32_t[]) {
+ (uint32_t[]){
0, /* back pixel: black */
XCB_EVENT_MASK_EXPOSURE |
XCB_EVENT_MASK_BUTTON_PRESS});
# };
# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
-# ┃ Run dmenu to ask the user for her choice ┃
+# ┃ Run dmenu to ask the user for their choice ┃
# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
# open2 will just make dmenu’s STDERR go to our own STDERR.
/* re-draw the background */
xcb_rectangle_t border = {0, 0, 500, font.height + 8}, inner = {2, 2, 496, font.height + 8 - 4};
- xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {get_colorpixel("#FF0000")});
+ xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){get_colorpixel("#FF0000")});
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &border);
- xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {get_colorpixel("#000000")});
+ xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){get_colorpixel("#000000")});
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &inner);
/* restore font color */
XCB_WINDOW_CLASS_INPUT_OUTPUT,
XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
- (uint32_t[]) {
+ (uint32_t[]){
0, /* back pixel: black */
1, /* override redirect: don’t manage this window */
XCB_EVENT_MASK_EXPOSURE});
# NOTE: This is not 100% accurate, as it only works for one level
# of nested containers. As this is a common use case, we use 'focus
# parent; $command' nevertheless. For advanced use cases, the user
- # has to modify his config.
+ # has to modify their config.
print "$statement $key focus parent; $command\n";
}
return;
* © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
*
* i3-nagbar is a utility which displays a nag message, for example in the case
- * when the user has an error in his configuration file.
+ * when the user has an error in their configuration file.
*
*/
#include <stdio.h>
*/
static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) {
/* re-draw the background */
- xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {color_background});
+ xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){color_background});
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &rect);
/* restore font color */
xcb_rectangle_t close = {y - w - (2 * line_width), 0, w + (2 * line_width), rect.height};
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &close);
- xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {color_border});
+ xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){color_border});
xcb_point_t points[] = {
{y - w - (2 * line_width), line_width / 2},
{y - (line_width / 2), line_width / 2},
/* account for left/right padding, which seems to be set to 12px (total) below */
w += 12;
y -= 30;
- xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {color_button_background});
- close = (xcb_rectangle_t) {y - w - (2 * line_width), 2, w + (2 * line_width), rect.height - 6};
+ xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){color_button_background});
+ close = (xcb_rectangle_t){y - w - (2 * line_width), 2, w + (2 * line_width), rect.height - 6};
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &close);
- xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {color_border});
+ xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){color_border});
buttons[c].x = y - w - (2 * line_width);
buttons[c].width = w;
xcb_point_t points2[] = {
XCB_WINDOW_CLASS_INPUT_OUTPUT,
XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
- (uint32_t[]) {
+ (uint32_t[]){
0, /* back pixel: black */
XCB_EVENT_MASK_EXPOSURE |
XCB_EVENT_MASK_STRUCTURE_NOTIFY |
case XCB_CONFIGURE_NOTIFY: {
xcb_configure_notify_event_t *configure_notify = (xcb_configure_notify_event_t *)event;
- rect = (xcb_rectangle_t) {
+ rect = (xcb_rectangle_t){
configure_notify->x,
configure_notify->y,
configure_notify->width,
# Font for window titles. Will also be used by the bar unless a different font
# is used in the bar {} block below.
+font pango:monospace 8
+
# This font is widely installed, provides lots of unicode glyphs, right-to-left
# text rendering and scalability on retina/hidpi displays (thanks to pango).
-font pango:DejaVu Sans Mono 8
+#font pango:DejaVu Sans Mono 8
+
# Before i3 v4.8, we used to recommend this one as the default:
# font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
# The font above is very space-efficient, that is, it looks good, sharp and
#######################################################################
# automatically start i3-config-wizard to offer the user to create a
-# keysym-based config which used his favorite modifier (alt or windows)
+# keysym-based config which used their favorite modifier (alt or windows)
#
# i3-config-wizard will not launch if there already is a config file
# in ~/.i3/config.
# Font for window titles. Will also be used by the bar unless a different font
# is used in the bar {} block below.
+font pango:monospace 8
+
# This font is widely installed, provides lots of unicode glyphs, right-to-left
# text rendering and scalability on retina/hidpi displays (thanks to pango).
-font pango:DejaVu Sans Mono 8
+#font pango:DejaVu Sans Mono 8
+
# Before i3 v4.8, we used to recommend this one as the default:
# font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
# The font above is very space-efficient, that is, it looks good, sharp and
typedef struct rect_t rect;
struct ev_loop *main_loop;
-char *statusline;
-char *statusline_buffer;
struct rect_t {
int x;
parser_ctx parser_context;
-/* The buffer statusline points to */
struct statusline_head statusline_head = TAILQ_HEAD_INITIALIZER(statusline_head);
-char *statusline_buffer = NULL;
+/* Used temporarily while reading a statusline */
+struct statusline_head statusline_buffer = TAILQ_HEAD_INITIALIZER(statusline_buffer);
int child_stdin;
/*
- * Clears all blocks from the statusline structure in memory and frees their
- * associated resources.
+ * Remove all blocks from the given statusline.
+ * If free_resources is set, the fields of each status block will be free'd.
*/
-static void clear_status_blocks() {
+static void clear_statusline(struct statusline_head *head, bool free_resources) {
struct status_block *first;
- while (!TAILQ_EMPTY(&statusline_head)) {
- first = TAILQ_FIRST(&statusline_head);
- I3STRING_FREE(first->full_text);
- TAILQ_REMOVE(&statusline_head, first, blocks);
+ while (!TAILQ_EMPTY(head)) {
+ first = TAILQ_FIRST(head);
+ if (free_resources) {
+ I3STRING_FREE(first->full_text);
+ FREE(first->color);
+ FREE(first->name);
+ FREE(first->instance);
+ }
+
+ TAILQ_REMOVE(head, first, blocks);
free(first);
}
}
+static void copy_statusline(struct statusline_head *from, struct statusline_head *to) {
+ struct status_block *current;
+ TAILQ_FOREACH(current, from, blocks) {
+ struct status_block *new_block = smalloc(sizeof(struct status_block));
+ memcpy(new_block, current, sizeof(struct status_block));
+ TAILQ_INSERT_TAIL(to, new_block, blocks);
+ }
+}
+
/*
* Replaces the statusline in memory with an error message. Pass a format
* string and format parameters as you would in `printf'. The next time
* the space allocated for the statusline.
*/
__attribute__((format(printf, 1, 2))) static void set_statusline_error(const char *format, ...) {
- clear_status_blocks();
+ clear_statusline(&statusline_head, true);
char *message;
va_list args;
if (stdin_io != NULL) {
ev_io_stop(main_loop, stdin_io);
FREE(stdin_io);
- FREE(statusline_buffer);
- /* statusline pointed to memory within statusline_buffer */
- statusline = NULL;
}
if (child_sig != NULL) {
/*
* The start of a new array is the start of a new status line, so we clear all
- * previous entries.
- *
+ * previous entries from the buffer.
*/
static int stdin_start_array(void *context) {
- struct status_block *first;
- while (!TAILQ_EMPTY(&statusline_head)) {
- first = TAILQ_FIRST(&statusline_head);
- I3STRING_FREE(first->full_text);
- FREE(first->color);
- FREE(first->name);
- FREE(first->instance);
- TAILQ_REMOVE(&statusline_head, first, blocks);
- free(first);
- }
+ // the blocks are still used by statusline_head, so we won't free the
+ // resources here.
+ clear_statusline(&statusline_buffer, false);
return 1;
}
static int stdin_string(void *context, const unsigned char *val, size_t len) {
parser_ctx *ctx = context;
if (strcasecmp(ctx->last_map_key, "full_text") == 0) {
- ctx->block.full_text = i3string_from_utf8_with_length((const char *)val, len);
+ ctx->block.full_text = i3string_from_markup_with_length((const char *)val, len);
}
if (strcasecmp(ctx->last_map_key, "color") == 0) {
sasprintf(&(ctx->block.color), "%.*s", len, val);
ctx->block.align = ALIGN_LEFT;
}
} else if (strcasecmp(ctx->last_map_key, "min_width") == 0) {
- i3String *text = i3string_from_utf8_with_length((const char *)val, len);
+ i3String *text = i3string_from_markup_with_length((const char *)val, len);
ctx->block.min_width = (uint32_t)predict_text_width(text);
i3string_free(text);
}
return 1;
}
+/*
+ * When a map is finished, we have an entire status block.
+ * Move it from the parser's context to the statusline buffer.
+ */
static int stdin_end_map(void *context) {
parser_ctx *ctx = context;
struct status_block *new_block = smalloc(sizeof(struct status_block));
new_block->full_text = i3string_from_utf8("SPEC VIOLATION: full_text is NULL!");
if (new_block->urgent)
ctx->has_urgent = true;
- TAILQ_INSERT_TAIL(&statusline_head, new_block, blocks);
+ TAILQ_INSERT_TAIL(&statusline_buffer, new_block, blocks);
return 1;
}
+/*
+ * When an array is finished, we have an entire statusline.
+ * Copy it from the buffer to the actual statusline.
+ */
static int stdin_end_array(void *context) {
+ DLOG("copying statusline_buffer to statusline_head\n");
+ clear_statusline(&statusline_head, true);
+ copy_statusline(&statusline_buffer, &statusline_head);
+
DLOG("dumping statusline:\n");
struct status_block *current;
TAILQ_FOREACH(current, &statusline_head, blocks) {
buffer[length - 1] = '\0';
else
buffer[length] = '\0';
- first->full_text = i3string_from_utf8(buffer);
+ first->full_text = i3string_from_markup(buffer);
}
static bool read_json_input(unsigned char *input, int length) {
kill_child();
- FREE(statusline_buffer);
-
clean_xcb();
ev_default_destroy();
/* Offset may be equal to length, in which case display the number */
params->workspaces_walk->name = (offset < len
- ? i3string_from_utf8_with_length(ws_name + offset, len - offset)
- : i3string_from_utf8(ws_num));
+ ? i3string_from_markup_with_length(ws_name + offset, len - offset)
+ : i3string_from_markup(ws_num));
} else {
/* Default case: just save the name */
- params->workspaces_walk->name = i3string_from_utf8_with_length(ws_name, len);
+ params->workspaces_walk->name = i3string_from_markup_with_length(ws_name, len);
}
/* Save its rendered width */
/* Draw the background */
uint32_t bg_color = colors.urgent_ws_bg;
- uint32_t bg_values[] = { bg_color, bg_color };
+ uint32_t bg_values[] = {bg_color, bg_color};
xcb_change_gc(xcb_connection, statusline_ctx, mask, bg_values);
/* The urgent background “overshoots” by 2 px so that the text that
* is printed onto it will not be look so cut off. */
- xcb_rectangle_t bg_rect = { x - logical_px(2), logical_px(1), block->width + logical_px(4), bar_height - logical_px(2) };
+ xcb_rectangle_t bg_rect = {x - logical_px(2), logical_px(1), block->width + logical_px(4), bar_height - logical_px(2)};
xcb_poly_fill_rectangle(xcb_connection, statusline_pm, statusline_ctx, 1, &bg_rect);
} else {
fg_color = (block->color ? get_colorpixel(block->color) : colors.bar_fg);
xcb_change_gc(xcb_connection, statusline_ctx, mask, values);
xcb_poly_line(xcb_connection, XCB_COORD_MODE_ORIGIN, statusline_pm,
statusline_ctx, 2,
- (xcb_point_t[]) { { x - sep_offset, logical_px(4) },
- { x - sep_offset, bar_height - logical_px(4) } });
+ (xcb_point_t[]){{x - sep_offset, logical_px(4)},
+ {x - sep_offset, bar_height - logical_px(4)}});
}
}
}
struct status_block *block;
int sep_offset_remainder = 0;
- TAILQ_FOREACH (block, &statusline_head, blocks) {
+ TAILQ_FOREACH(block, &statusline_head, blocks) {
if (i3string_get_num_bytes(block->full_text) == 0)
continue;
last_block_x = block_x;
- block_x += block->width + block->x_offset + block->x_append
- + get_sep_offset(block) + sep_offset_remainder;
+ block_x += block->width + block->x_offset + block->x_append + get_sep_offset(block) + sep_offset_remainder;
if (x <= block_x && x >= last_block_x) {
send_block_clicked(event->detail, block->name, block->instance, event->root_x, event->root_y);
}
/* TODO: Move this to extern get_ws_for_output() */
- TAILQ_FOREACH (cur_ws, walk->workspaces, tailq) {
+ TAILQ_FOREACH(cur_ws, walk->workspaces, tailq) {
if (cur_ws->visible) {
break;
}
int num_visible = 0;
i3_output *output;
- SLIST_FOREACH (output, outputs, slist) {
+ SLIST_FOREACH(output, outputs, slist) {
if (!output->active) {
continue;
}
xmacro(_NET_REQUEST_FRAME_EXTENTS)
xmacro(_NET_FRAME_EXTENTS)
xmacro(_MOTIF_WM_HINTS)
-xmacro(WM_CHANGE_STATE)
/** By default, focus follows mouse. If the user explicitly wants to
* turn this off (and instead rely only on the keyboard for changing
- * focus), we allow him to do this with this relatively special option.
+ * focus), we allow them to do this with this relatively special option.
* It is not planned to add any different focus models. */
bool disable_focus_follows_mouse;
/**
* An Assignment makes specific windows go to a specific workspace/output or
* run a command for that window. With this mechanism, the user can -- for
- * example -- assign his browser to workspace "www". Checking if a window is
+ * example -- assign their browser to workspace "www". Checking if a window is
* assigned works by comparing the Match data structure with the window (see
* match_matches_window()).
*
/**
* Kills the commanderror i3-nagbar process, if any.
*
- * Called when reloading/restarting, since the user probably fixed his wrong
+ * Called when reloading/restarting, since the user probably fixed their wrong
* keybindings.
*
* If wait_for_it is set (restarting), this function will waitpid(), otherwise,
*/
i3String *i3string_from_utf8(const char *from_utf8);
+/**
+ * Build an i3String from an UTF-8 encoded string in Pango markup.
+ *
+ */
+i3String *i3string_from_markup(const char *from_markup);
+
/**
* Build an i3String from an UTF-8 encoded string with fixed length.
* To be used when no proper NUL-terminaison is available.
*/
i3String *i3string_from_utf8_with_length(const char *from_utf8, size_t num_bytes);
+/**
+ * Build an i3String from an UTF-8 encoded string in Pango markup with fixed
+ * length.
+ *
+ */
+i3String *i3string_from_markup_with_length(const char *from_markup, size_t num_bytes);
+
/**
* Build an i3String from an UCS-2 encoded string.
* Returns the newly-allocated i3String.
*/
size_t i3string_get_num_bytes(i3String *str);
+/**
+ * Whether the given i3String is in Pango markup.
+ */
+bool i3string_is_markup(i3String *str);
+
/**
* Returns the number of glyphs in an i3String.
*
*
*/
static void draw_text_pango(const char *text, size_t text_len,
- xcb_drawable_t drawable, int x, int y, int max_width) {
+ xcb_drawable_t drawable, int x, int y,
+ int max_width, bool is_markup) {
/* Create the Pango layout */
/* root_visual_type is cached in load_pango_font */
cairo_surface_t *surface = cairo_xcb_surface_create(conn, drawable,
pango_layout_set_wrap(layout, PANGO_WRAP_CHAR);
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
- pango_layout_set_text(layout, text, text_len);
+ if (is_markup)
+ pango_layout_set_markup(layout, text, text_len);
+ else
+ pango_layout_set_text(layout, text, text_len);
/* Do the drawing */
cairo_set_source_rgb(cr, pango_font_red, pango_font_green, pango_font_blue);
pango_cairo_update_layout(cr, layout);
pango_layout_get_pixel_size(layout, NULL, &height);
- cairo_move_to(cr, x, y - (height - savedFont->height));
+ cairo_move_to(cr, x, y - 0.5 * (height - savedFont->height));
pango_cairo_show_layout(cr, layout);
/* Free resources */
* Calculate the text width using Pango rendering.
*
*/
-static int predict_text_width_pango(const char *text, size_t text_len) {
+static int predict_text_width_pango(const char *text, size_t text_len, bool is_markup) {
/* Create a dummy Pango layout */
/* root_visual_type is cached in load_pango_font */
cairo_surface_t *surface = cairo_xcb_surface_create(conn, root_screen->root, root_visual_type, 1, 1);
/* Get the font width */
gint width;
pango_layout_set_font_description(layout, savedFont->specific.pango_desc);
- pango_layout_set_text(layout, text, text_len);
+
+ if (is_markup)
+ pango_layout_set_markup(layout, text, text_len);
+ else
+ pango_layout_set_text(layout, text, text_len);
+
pango_cairo_update_layout(cr, layout);
pango_layout_get_pixel_size(layout, &width, NULL);
case FONT_TYPE_PANGO:
/* Render the text using Pango */
draw_text_pango(i3string_as_utf8(text), i3string_get_num_bytes(text),
- drawable, x, y, max_width);
+ drawable, x, y, max_width, i3string_is_markup(text));
return;
#endif
default:
case FONT_TYPE_PANGO:
/* Render the text using Pango */
draw_text_pango(text, strlen(text),
- drawable, x, y, max_width);
+ drawable, x, y, max_width, false);
return;
#endif
default:
cookie, &error);
if (reply == NULL) {
/* We return a safe estimate because a rendering error is better than
- * a crash. Plus, the user will see the error in his log. */
+ * a crash. Plus, the user will see the error in their log. */
fprintf(stderr, "Could not get text extents (X error code %d)\n",
error->error_code);
return savedFont->specific.xcb.info->max_bounds.character_width * text_len;
#if PANGO_SUPPORT
case FONT_TYPE_PANGO:
/* Calculate extents using Pango */
- return predict_text_width_pango(i3string_as_utf8(text), i3string_get_num_bytes(text));
+ return predict_text_width_pango(i3string_as_utf8(text), i3string_get_num_bytes(text),
+ i3string_is_markup(text));
#endif
default:
assert(false);
xcb_char2b_t *ucs2;
size_t num_glyphs;
size_t num_bytes;
+ bool is_markup;
};
/*
return str;
}
+/*
+ * Build an i3String from an UTF-8 encoded string in Pango markup.
+ *
+ */
+i3String *i3string_from_markup(const char *from_markup) {
+ i3String *str = i3string_from_utf8(from_markup);
+
+ /* Set the markup flag */
+ str->is_markup = true;
+
+ return str;
+}
+
/*
* Build an i3String from an UTF-8 encoded string with fixed length.
* To be used when no proper NUL-terminaison is available.
return str;
}
+/*
+ * Build an i3String from an UTF-8 encoded string in Pango markup with fixed
+ * length.
+ *
+ */
+i3String *i3string_from_markup_with_length(const char *from_markup, size_t num_bytes) {
+ i3String *str = i3string_from_utf8_with_length(from_markup, num_bytes);
+
+ /* set the markup flag */
+ str->is_markup = true;
+
+ return str;
+}
+
/*
* Build an i3String from an UCS-2 encoded string.
* Returns the newly-allocated i3String.
return str->num_bytes;
}
+/*
+ * Whether the given i3String is in Pango markup.
+ */
+bool i3string_is_markup(i3String *str) {
+ return str->is_markup;
+}
+
/*
* Returns the number of glyphs in an i3String.
*
<refentrytitle>{mantitle}</refentrytitle>
<manvolnum>{manvolnum}</manvolnum>
<refmiscinfo class="source">i3</refmiscinfo>
-<refmiscinfo class="version">4.8</refmiscinfo>
+<refmiscinfo class="version">4.9.1</refmiscinfo>
<refmiscinfo class="manual">i3 Manual</refmiscinfo>
</refmeta>
<refnamediv>
* gedit
* mc-edit
-Please don’t complain about the order: If the user has any preference, he will
+Please don’t complain about the order: If the user has any preference, they will
have $VISUAL or $EDITOR set.
== SEE ALSO
* w3m
* i3-sensible-editor(1)
-Please don’t complain about the order: If the user has any preference, he will
+Please don’t complain about the order: If the user has any preference, they will
have $PAGER set.
== SEE ALSO
* roxterm
* xfce4-terminal
-Please don’t complain about the order: If the user has any preference, she will
-have $TERMINAL set or modified her i3 configuration file.
+Please don’t complain about the order: If the user has any preference, they will
+have $TERMINAL set or modified their i3 configuration file.
== SEE ALSO
--- /dev/null
+#!/bin/zsh
+# This script is used to prepare a new release of i3.
+
+export RELEASE_VERSION="4.9.1"
+export PREVIOUS_VERSION="4.9"
+export RELEASE_BRANCH="master"
+
+if [ ! -e "../i3.github.io" ]
+then
+ echo "../i3.github.io does not exist."
+ echo "Use git clone git://github.com/i3/i3.github.io"
+ exit 1
+fi
+
+if [ ! -e "RELEASE-NOTES-${RELEASE_VERSION}" ]
+then
+ echo "RELEASE-NOTES-${RELEASE_VERSION} not found."
+ exit 1
+fi
+
+if git diff-files --quiet --exit-code debian/changelog
+then
+ echo "Expected debian/changelog to be changed (containing the changelog for ${RELEASE_VERSION})."
+ exit 1
+fi
+
+eval $(gpg-agent --daemon)
+export GPG_AGENT_INFO
+
+################################################################################
+# Section 1: update git and build the release tarball
+################################################################################
+
+STARTDIR=$PWD
+
+TMPDIR=$(mktemp -d)
+cd $TMPDIR
+if ! wget http://i3wm.org/downloads/i3-${PREVIOUS_VERSION}.tar.bz2; then
+ echo "Could not download i3-${PREVIOUS_VERSION}.tar.bz2 (required for comparing files)."
+ exit 1
+fi
+git clone --quiet --branch "${RELEASE_BRANCH}" file://${STARTDIR}
+cd i3
+if [ ! -e "${STARTDIR}/RELEASE-NOTES-${RELEASE_VERSION}" ]; then
+ echo "Required file RELEASE-NOTES-${RELEASE_VERSION} not found."
+ exit 1
+fi
+git checkout -b release-${RELEASE_VERSION}
+cp "${STARTDIR}/RELEASE-NOTES-${RELEASE_VERSION}" "RELEASE-NOTES-${RELEASE_VERSION}"
+git add RELEASE-NOTES-${RELEASE_VERSION}
+git rm RELEASE-NOTES-${PREVIOUS_VERSION}
+sed -i "s,<refmiscinfo class=\"version\">[^<]*</refmiscinfo>,<refmiscinfo class=\"version\">${RELEASE_VERSION}</refmiscinfo>,g" man/asciidoc.conf
+git commit -a -m "release i3 ${RELEASE_VERSION}"
+git tag "${RELEASE_VERSION}" -m "release i3 ${RELEASE_VERSION}" --sign --local-user=0x4AC8EE1D
+
+make dist
+
+echo "Differences in the release tarball file lists:"
+
+diff -u \
+ <(tar tf ../i3-${PREVIOUS_VERSION}.tar.bz2 | sed "s,i3-${PREVIOUS_VERSION}/,,g" | sort) \
+ <(tar tf i3-${RELEASE_VERSION}.tar.bz2 | sed "s,i3-${RELEASE_VERSION}/,,g" | sort) \
+ | colordiff
+
+if ! tar xf i3-${RELEASE_VERSION}.tar.bz2 --to-stdout --strip-components=1 i3-${RELEASE_VERSION}/I3_VERSION | grep -q "^${RELEASE_VERSION} "
+then
+ echo "I3_VERSION file does not start with ${RELEASE_VERSION}"
+ exit 1
+fi
+
+gpg --armor -b i3-${RELEASE_VERSION}.tar.bz2
+
+if [ "${RELEASE_BRANCH}" = "master" ]; then
+ git checkout master
+ git merge --no-ff release-${RELEASE_VERSION} -m "Merge branch 'release-${RELEASE_VERSION}'"
+ git checkout next
+ git merge --no-ff master -m "Merge branch 'master' into next"
+else
+ git checkout next
+ git merge --no-ff release-${RELEASE_VERSION} -m "Merge branch 'release-${RELEASE_VERSION}'"
+ git checkout master
+ git merge --no-ff next -m "Merge branch 'next' into master"
+fi
+
+################################################################################
+# Section 2: Debian packaging
+################################################################################
+
+cd "${TMPDIR}"
+mkdir debian
+
+# Copy over the changelog because we expect it to be locally modified in the
+# start directory.
+cp "${STARTDIR}/debian/changelog" i3/debian/changelog
+
+cat > ${TMPDIR}/Dockerfile <<EOT
+FROM debian:sid
+RUN sed -i 's,^deb \(.*\),deb \1\ndeb-src \1,g' /etc/apt/sources.list
+RUN apt-get update && apt-get install -y dpkg-dev devscripts
+COPY i3/i3-${RELEASE_VERSION}.tar.bz2 /usr/src/i3-wm_${RELEASE_VERSION}.orig.tar.bz2
+WORKDIR /usr/src/
+RUN tar xf i3-wm_${RELEASE_VERSION}.orig.tar.bz2
+WORKDIR /usr/src/i3-${RELEASE_VERSION}
+COPY i3/debian /usr/src/i3-${RELEASE_VERSION}/debian/
+RUN mkdir debian/source
+RUN echo '3.0 (quilt)' > debian/source/format
+WORKDIR /usr/src
+RUN mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' i3-${RELEASE_VERSION}/debian/control
+WORKDIR /usr/src/i3-${RELEASE_VERSION}
+RUN dpkg-buildpackage -sa -j8
+EOT
+
+CONTAINER_NAME=$(echo "i3-${TMPDIR}" | sed 's,/,,g')
+docker build -t i3 .
+for file in $(docker run --name "${CONTAINER_NAME}" i3 /bin/sh -c "ls /usr/src/i3*_${RELEASE_VERSION}*")
+do
+ docker cp "${CONTAINER_NAME}:${file}" ${TMPDIR}/debian/
+done
+
+echo "Content of resulting package’s .changes file:"
+cat ${TMPDIR}/debian/*.changes
+
+# debsign is in devscripts, which is available in fedora and debian
+debsign -k4AC8EE1D ${TMPDIR}/debian/*.changes
+
+# TODO: docker cleanup
+
+################################################################################
+# Section 3: website
+################################################################################
+
+cd ${TMPDIR}
+git clone --quiet ${STARTDIR}/../i3.github.io
+cd i3.github.io
+cp ${TMPDIR}/i3/i3-${RELEASE_VERSION}.tar.bz2* downloads/
+git add downloads/i3-${RELEASE_VERSION}.tar.bz2*
+cp ${TMPDIR}/i3/RELEASE-NOTES-${RELEASE_VERSION} downloads/RELEASE-NOTES-${RELEASE_VERSION}.txt
+git add downloads/RELEASE-NOTES-${RELEASE_VERSION}.txt
+sed -i "s,<h2>Documentation for i3 v[^<]*</h2>,<h2>Documentation for i3 v${RELEASE_VERSION}</h2>,g" docs/index.html
+sed -i "s,<span style=\"margin-left: 2em; color: #c0c0c0\">[^<]*</span>,<span style=\"margin-left: 2em; color: #c0c0c0\">${RELEASE_VERSION}</span>,g" index.html
+sed -i "s,The current stable version is .*$,The current stable version is ${RELEASE_VERSION}.,g" downloads/index.html
+sed -i "s,<tbody>,<tbody>\n <tr>\n <td>${RELEASE_VERSION}</td>\n <td><a href=\"/downloads/i3-${RELEASE_VERSION}.tar.bz2\">i3-${RELEASE_VERSION}.tar.bz2</a></td>\n <td>$(ls -lh ../i3/i3-${RELEASE_VERSION}.tar.bz2 | awk -F " " {'print $5'} | sed 's/K$/ KiB/g')</td>\n <td><a href=\"/downloads/i3-${RELEASE_VERSION}.tar.bz2.asc\">signature</a></td>\n <td>$(date +'%Y-%m-%d')</td>\n <td><a href=\"/downloads/RELEASE-NOTES-${RELEASE_VERSION}.txt\">release notes</a></td>\n </tr>\n,g" downloads/index.html
+
+git commit -a -m "add ${RELEASE_VERSION} release"
+
+mkdir docs/${PREVIOUS_VERSION}
+tar cf - '--exclude=[0-9]\.[0-9e]*' docs | tar xf - --strip-components=1 -C docs/${PREVIOUS_VERSION}
+git add docs/${PREVIOUS_VERSION}
+git commit -a -m "save docs for ${PREVIOUS_VERSION}"
+
+for i in $(find _docs -maxdepth 1 -and -type f -and \! -regex ".*\.\(html\|man\)$" -and \! -name "Makefile")
+do
+ base="$(basename $i)"
+ [ -e "${STARTDIR}/docs/${base}" ] && cp "${STARTDIR}/docs/${base}" "_docs/${base}"
+done
+
+(cd _docs && make)
+
+for i in $(find _docs -maxdepth 1 -and -type f -and \! -regex ".*\.\(html\|man\)$" -and \! -name "Makefile")
+do
+ base="$(basename $i)"
+ [ -e "${STARTDIR}/docs/${base}" ] && cp "_docs/${base}.html" docs/
+done
+
+git commit -a -m "update docs for ${RELEASE_VERSION}"
+
+################################################################################
+# Section 4: final push instructions
+################################################################################
+
+echo "As a final sanity check, install the debian package and see whether i3 works."
+
+echo "When satisfied, run:"
+echo " cd ${TMPDIR}/i3"
+echo " git checkout next"
+echo " vi debian/changelog"
+# TODO: can we just set up the remote spec properly?
+echo " git push git@github.com:i3/i3 next"
+echo " git push git@github.com:i3/i3 master"
+echo " git push git@github.com:i3/i3 --tags"
+echo ""
+echo " cd ${TMPDIR}/i3.github.io"
+# TODO: can we just set up the remote spec properly?
+echo " git push git@github.com:i3/i3.github.io master"
+echo ""
+echo " cd ${TMPDIR}/debian"
+echo " dput *.changes"
+echo ""
+echo "Announce on:"
+echo " twitter"
+echo " google+"
+echo " mailing list"
+echo " #i3 topic"
* need to look in the array of translated keycodes for the event’s
* keycode */
if (input_type == B_KEYBOARD && bind->symbol != NULL) {
+ xcb_keycode_t input_keycode = (xcb_keycode_t)input_code;
if (memmem(bind->translated_to,
bind->number_keycodes * sizeof(xcb_keycode_t),
- &input_code, sizeof(xcb_keycode_t)) == NULL)
+ &input_keycode, sizeof(xcb_keycode_t)) == NULL)
continue;
} else {
/* This case is easier: The user specified a keycode */
state_filtered &= 0xFF;
DLOG("(removed upper 8 bits, state = %d)\n", state_filtered);
- if (xkb_current_group == XkbGroup2Index)
+ if (xkb_current_group == XCB_XKB_GROUP_2)
state_filtered |= BIND_MODE_SWITCH;
DLOG("(checked mode_switch, state %d)\n", state_filtered);
bind->translated_to[bind->number_keycodes - 1] = i;
}
- DLOG("Translated symbol \"%s\" to %d keycode\n", bind->symbol,
- bind->number_keycodes);
+ DLOG("Translated symbol \"%s\" to %d keycode (mods %d)\n", bind->symbol,
+ bind->number_keycodes, bind->mods);
}
}
return 0;
}
- if (event->child != XCB_NONE) {
- DLOG("event->child not XCB_NONE, so this is an event which originated from a click into the application, but the application did not handle it.\n");
- return route_click(con, event, mod_pressed, CLICK_INSIDE);
- }
-
/* Check if the click was on the decoration of a child */
Con *child;
TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
return route_click(child, event, mod_pressed, CLICK_DECORATION);
}
+ if (event->child != XCB_NONE) {
+ DLOG("event->child not XCB_NONE, so this is an event which originated from a click into the application, but the application did not handle it.\n");
+ return route_click(con, event, mod_pressed, CLICK_INSIDE);
+ }
+
return route_click(con, event, mod_pressed, CLICK_BORDER);
}
y(map_close); \
} \
} while (0)
-#define yerror(message) \
- do { \
- if (cmd_output->json_gen != NULL) { \
- y(map_open); \
- ystr("success"); \
- y(bool, false); \
- ystr("error"); \
- ystr(message); \
- y(map_close); \
- } \
+#define yerror(format, ...) \
+ do { \
+ if (cmd_output->json_gen != NULL) { \
+ char *message; \
+ sasprintf(&message, format, ##__VA_ARGS__); \
+ y(map_open); \
+ ystr("success"); \
+ y(bool, false); \
+ ystr("error"); \
+ ystr(message); \
+ y(map_close); \
+ free(message); \
+ } \
} while (0)
/** When the command did not include match criteria (!), we use the currently
if (parsed_num == -1) {
LOG("Could not parse initial part of \"%s\" as a number.\n", which);
- // TODO: better error message
- yerror("Could not parse number");
+ yerror("Could not parse number \"%s\"", which);
return;
}
void cmd_append_layout(I3_CMD, char *path) {
LOG("Appending layout \"%s\"\n", path);
+ /* Make sure we allow paths like '~/.i3/layout.json' */
+ path = resolve_tilde(path);
+
json_content_t content = json_determine_content(path);
LOG("JSON content = %d\n", content);
if (content == JSON_CONTENT_UNKNOWN) {
ELOG("Could not determine the contents of \"%s\", not loading.\n", path);
- ysuccess(false);
+ yerror("Could not determine the contents of \"%s\".", path);
+ free(path);
return;
}
if (content == JSON_CONTENT_WORKSPACE)
ipc_send_workspace_event("restored", parent, NULL);
+ free(path);
cmd_output->needs_tree_render = true;
}
if (parsed_num == -1) {
LOG("Could not parse initial part of \"%s\" as a number.\n", which);
- // TODO: better error message
- yerror("Could not parse number");
+ yerror("Could not parse number \"%s\"", which);
return;
}
}
if (!workspace) {
- // TODO: we should include the old workspace name here and use yajl for
- // generating the reply.
- // TODO: better error message
- yerror("Old workspace not found");
+ yerror("Old workspace \"%s\" not found", old_name);
return;
}
!strcasecmp(child->name, new_name));
if (check_dest != NULL) {
- // TODO: we should include the new workspace name here and use yajl for
- // generating the reply.
- // TODO: better error message
- yerror("New workspace already exists");
+ yerror("New workspace \"%s\" already exists", new_name);
return;
}
/* Shortcut to avoid calling con_adjacent_borders() on dock containers. */
int border_style = con_border_style(con);
if (border_style == BS_NONE)
- return (Rect) {0, 0, 0, 0};
+ return (Rect){0, 0, 0, 0};
borders_to_hide = con_adjacent_borders(con) & config.hide_edge_borders;
if (border_style == BS_NORMAL) {
- result = (Rect) {border_width, 0, -(2 * border_width), -(border_width)};
+ result = (Rect){border_width, 0, -(2 * border_width), -(border_width)};
} else {
- result = (Rect) {border_width, border_width, -(2 * border_width), -(2 * border_width)};
+ result = (Rect){border_width, border_width, -(2 * border_width), -(2 * border_width)};
}
/* Floating windows are never adjacent to any other window, so
if (con_is_leaf(con)) {
DLOG("leaf node, returning 75x50\n");
- return (Rect) {0, 0, 75, 50};
+ return (Rect){0, 0, 75, 50};
}
if (con->type == CT_FLOATING_CON) {
}
DLOG("stacked/tabbed now, returning %d x %d + deco_rect = %d\n",
max_width, max_height, deco_height);
- return (Rect) {0, 0, max_width, max_height + deco_height};
+ return (Rect){0, 0, max_width, max_height + deco_height};
}
/* For horizontal/vertical split containers we sum up the width (h-split)
}
}
DLOG("split container, returning width = %d x height = %d\n", width, height);
- return (Rect) {0, 0, width, height};
+ return (Rect){0, 0, width, height};
}
ELOG("Unhandled case, type = %d, layout = %d, split = %d\n",
fprintf(stderr, "Migration process exit code was != 0\n");
if (returncode == 2) {
fprintf(stderr, "could not start the migration script\n");
- /* TODO: script was not found. tell the user to fix his system or create a v4 config */
+ /* TODO: script was not found. tell the user to fix their system or create a v4 config */
} else if (returncode == 1) {
fprintf(stderr, "This already was a v4 config. Please add the following line to your config file:\n");
fprintf(stderr, "# i3 config file (v4)\n");
- /* TODO: nag the user with a message to include a hint for i3 in his config file */
+ /* TODO: nag the user with a message to include a hint for i3 in their config file */
}
return NULL;
}
dest_height = max(dest_height, (int)(dest_width / ratio));
}
- con->rect = (Rect) {dest_x, dest_y, dest_width, dest_height};
+ con->rect = (Rect){dest_x, dest_y, dest_width, dest_height};
/* Obey window size */
floating_check_size(con);
return;
}
- /* Focus the output on which the user moved his cursor */
+ /* Focus the output on which the user moved their cursor */
Con *old_focused = focused;
Con *next = con_descend_focused(output_get_content(output->con));
/* Since we are switching outputs, this *must* be a different workspace, so
enter_child = true;
}
- /* If not, then the user moved his cursor to the root window. In that case, we adjust c_ws */
+ /* If not, then the user moved their cursor to the root window. In that case, we adjust c_ws */
if (con == NULL) {
DLOG("Getting screen at %d x %d\n", event->root_x, event->root_y);
check_crossing_screen_boundary(event->root_x, event->root_y);
return;
}
-#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
-#define _NET_WM_MOVERESIZE_SIZE_TOP 1
-#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
-#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
-#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
-#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
-#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
-#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
-#define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
-#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */
-#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
-#define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
+#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
+#define _NET_WM_MOVERESIZE_SIZE_TOP 1
+#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
+#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
+#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
+#define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
+#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */
+#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
+#define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
/*
* Handle client messages (EWMH)
XCB_ATOM_CARDINAL, 32, 4,
&r);
xcb_flush(conn);
- } else if (event->type == A_WM_CHANGE_STATE) {
- /* http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.4 */
- Con *con = con_by_window_id(event->window);
-
- if (con && event->data.data32[0] == 3) {
- /* this request is so we can play some animiation showing the
- * window physically moving to the tray before we close it (I
- * think) */
- DLOG("Client has requested iconic state. Closing this con. (con = %p)\n", con);
- tree_close(con, DONT_KILL_WINDOW, false, false);
- tree_render();
- } else {
- DLOG("Not handling WM_CHANGE_STATE request. (window = %d, state = %d)\n", event->window, event->data.data32[0]);
- }
-
} else if (event->type == A__NET_CURRENT_DESKTOP) {
/* This request is used by pagers and bars to change the current
* desktop likely as a result of some user action. We interpret this as
DLOG("xkb event, need to handle it.\n");
xcb_xkb_state_notify_event_t *state = (xcb_xkb_state_notify_event_t *)event;
- if (state->xkbType == XCB_XKB_MAP_NOTIFY) {
+ if (state->xkbType == XCB_XKB_NEW_KEYBOARD_NOTIFY) {
+ DLOG("xkb new keyboard notify, sequence %d, time %d\n", state->sequence, state->time);
+ xcb_key_symbols_free(keysyms);
+ keysyms = xcb_key_symbols_alloc(conn);
+ ungrab_all_keys(conn);
+ translate_keysyms();
+ grab_all_keys(conn, false);
+ } else if (state->xkbType == XCB_XKB_MAP_NOTIFY) {
if (event_is_ignored(event->sequence, type)) {
DLOG("Ignoring map notify event for sequence %d.\n", state->sequence);
} else {
DLOG("xkb map notify, sequence %d, time %d\n", state->sequence, state->time);
add_ignore_event(event->sequence, type);
+ xcb_key_symbols_free(keysyms);
+ keysyms = xcb_key_symbols_alloc(conn);
ungrab_all_keys(conn);
translate_keysyms();
grab_all_keys(conn, false);
/* See The XKB Extension: Library Specification, section 14.1 */
/* We check if the current group (each group contains
* two levels) has been changed. Mode_switch activates
- * group XkbGroup2Index */
+ * group XCB_XKB_GROUP_2 */
if (xkb_current_group == state->group)
return;
xkb_current_group = state->group;
grab_all_keys(conn, false);
} else {
DLOG("Mode_switch enabled\n");
- grab_all_keys(conn, false);
+ grab_all_keys(conn, true);
}
}
handle_motion_notify((xcb_motion_notify_event_t *)event);
break;
- /* Enter window = user moved his mouse over the window */
+ /* Enter window = user moved their mouse over the window */
case XCB_ENTER_NOTIFY:
handle_enter_notify((xcb_enter_notify_event_t *)event);
break;
y(integer, bind->keycode);
ystr("input_type");
- ystr((const char*)(bind->input_type == B_KEYBOARD ? "keyboard" : "mouse"));
+ ystr((const char *)(bind->input_type == B_KEYBOARD ? "keyboard" : "mouse"));
ystr("symbol");
if (bind->symbol == NULL)
ystr("transient_for");
if (con->window->transient_for == XCB_NONE)
y(null);
- else y(integer, con->window->transient_for);
+ else
+ y(integer, con->window->transient_for);
y(map_close);
}
}
xcb_void_cookie_t cookie;
- cookie = xcb_change_window_attributes_checked(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]) {ROOT_EVENT_MASK});
+ cookie = xcb_change_window_attributes_checked(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){ROOT_EVENT_MASK});
check_error(conn, cookie, "Another window manager seems to be running");
xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(conn, gcookie, NULL);
xcb_xkb_use_extension(conn, XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION);
xcb_xkb_select_events(conn,
XCB_XKB_ID_USE_CORE_KBD,
- XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY,
+ XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY,
0,
- XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY,
+ XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY,
0xff,
0xff,
NULL);
xcb_create_gc(conn, gc, root->root,
XCB_GC_FUNCTION | XCB_GC_PLANE_MASK | XCB_GC_FILL_STYLE | XCB_GC_SUBWINDOW_MODE,
- (uint32_t[]) {XCB_GX_COPY, ~0, XCB_FILL_STYLE_SOLID, XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS});
+ (uint32_t[]){XCB_GX_COPY, ~0, XCB_FILL_STYLE_SOLID, XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS});
xcb_copy_area(conn, root->root, pixmap, gc, 0, 0, 0, 0, width, height);
- xcb_change_window_attributes_checked(conn, root->root, XCB_CW_BACK_PIXMAP, (uint32_t[]) {pixmap});
+ xcb_change_window_attributes_checked(conn, root->root, XCB_CW_BACK_PIXMAP, (uint32_t[]){pixmap});
xcb_flush(conn);
xcb_free_gc(conn, gc);
xcb_free_pixmap(conn, pixmap);
ELOG("Could not setup signal handler");
/* Ignore SIGPIPE to survive errors when an IPC client disconnects
- * while we are sending him a message */
+ * while we are sending them a message */
signal(SIGPIPE, SIG_IGN);
/* Autostarting exec-lines */
/* Strictly speaking, this line doesn’t really belong here, but since we
* are syncing, let’s un-register as a window manager first */
- xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]) {XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT});
+ xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT});
/* Make sure our changes reach the X server, we restart/exit now */
xcb_aux_sync(conn);
* which are not managed by the wm anyways). We store the original geometry
* here because it’s used for dock clients. */
if (nc->geometry.width == 0)
- nc->geometry = (Rect) {geom->x, geom->y, geom->width, geom->height};
+ nc->geometry = (Rect){geom->x, geom->y, geom->width, geom->height};
if (motif_border_style != BS_NORMAL) {
DLOG("MOTIF_WM_HINTS specifies decorations (border_style = %d)\n", motif_border_style);
/* depending on the border style, the rect of the child window
* needs to be smaller */
Rect *inset = &(con->window_rect);
- *inset = (Rect) {0, 0, con->rect.width, con->rect.height};
+ *inset = (Rect){0, 0, con->rect.width, con->rect.height};
if (!render_fullscreen)
*inset = rect_add(*inset, con_border_style_rect(con));
transient_con->window != NULL &&
transient_con->window->transient_for != XCB_NONE) {
DLOG("transient_con = 0x%08x, transient_con->window->transient_for = 0x%08x, fullscreen_id = 0x%08x\n",
- transient_con->window->id, transient_con->window->transient_for, fullscreen->window->id);
+ transient_con->window->id, transient_con->window->transient_for, fullscreen->window->id);
if (transient_con->window->transient_for == fullscreen->window->id) {
is_transient_for = true;
break;
static void update_placeholder_contents(placeholder_state *state) {
xcb_change_gc(restore_conn, state->gc, XCB_GC_FOREGROUND,
- (uint32_t[]) {config.client.placeholder.background});
+ (uint32_t[]){config.client.placeholder.background});
xcb_poly_fill_rectangle(restore_conn, state->pixmap, state->gc, 1,
- (xcb_rectangle_t[]) {{0, 0, state->rect.width, state->rect.height}});
+ (xcb_rectangle_t[]){{0, 0, state->rect.width, state->rect.height}});
// TODO: make i3font functions per-connection, at least these two for now…?
xcb_flush(restore_conn);
XCURSOR_CURSOR_POINTER,
true,
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
- (uint32_t[]) {
+ (uint32_t[]){
config.client.placeholder.background,
XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY,
});
xcb_create_pixmap(restore_conn, root_depth, state->pixmap,
state->window, state->rect.width, state->rect.height);
state->gc = xcb_generate_id(restore_conn);
- xcb_create_gc(restore_conn, state->gc, state->pixmap, XCB_GC_GRAPHICS_EXPOSURES, (uint32_t[]) {0});
+ xcb_create_gc(restore_conn, state->gc, state->pixmap, XCB_GC_GRAPHICS_EXPOSURES, (uint32_t[]){0});
update_placeholder_contents(state);
TAILQ_INSERT_TAIL(&state_head, state, state);
Match *temp_id = smalloc(sizeof(Match));
match_init(temp_id);
temp_id->id = placeholder;
- TAILQ_INSERT_TAIL(&(con->swallow_head), temp_id, matches);
+ TAILQ_INSERT_HEAD(&(con->swallow_head), temp_id, matches);
}
Con *child;
xcb_create_pixmap(restore_conn, root_depth, state->pixmap,
state->window, state->rect.width, state->rect.height);
state->gc = xcb_generate_id(restore_conn);
- xcb_create_gc(restore_conn, state->gc, state->pixmap, XCB_GC_GRAPHICS_EXPOSURES, (uint32_t[]) {0});
+ xcb_create_gc(restore_conn, state->gc, state->pixmap, XCB_GC_GRAPHICS_EXPOSURES, (uint32_t[]){0});
update_placeholder_contents(state);
xcb_copy_area(restore_conn, state->pixmap, state->window, state->gc,
/* re-draw the background */
xcb_rectangle_t border = {0, 0, width, height},
inner = {2, 2, width - 4, height - 4};
- xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {get_colorpixel("#FF0000")});
+ xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){get_colorpixel("#FF0000")});
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &border);
- xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {get_colorpixel("#000000")});
+ xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){get_colorpixel("#000000")});
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &inner);
/* restore font color */
/* TODO: refactor the following */
croot = con_new(NULL, NULL);
- croot->rect = (Rect) {
+ croot->rect = (Rect){
geometry->x,
geometry->y,
geometry->width,
croot->name = "root";
croot->type = CT_ROOT;
croot->layout = L_SPLITH;
- croot->rect = (Rect) {
+ croot->rect = (Rect){
geometry->x,
geometry->y,
geometry->width,
* unmap the window,
* then reparent it to the root window. */
xcb_change_window_attributes(conn, con->window->id,
- XCB_CW_EVENT_MASK, (uint32_t[]) {XCB_NONE});
+ XCB_CW_EVENT_MASK, (uint32_t[]){XCB_NONE});
xcb_unmap_window(conn, con->window->id);
cookie = xcb_reparent_window(conn, con->window->id, root, 0, 0);
}
Rect rect_add(Rect a, Rect b) {
- return (Rect) {a.x + b.x,
- a.y + b.y,
- a.width + b.width,
- a.height + b.height};
+ return (Rect){a.x + b.x,
+ a.y + b.y,
+ a.width + b.width,
+ a.height + b.height};
}
Rect rect_sub(Rect a, Rect b) {
- return (Rect) {a.x - b.x,
- a.y - b.y,
- a.width - b.width,
- a.height - b.height};
+ return (Rect){a.x - b.x,
+ a.y - b.y,
+ a.width - b.width,
+ a.height - b.height};
}
/*
DLOG("Reserved pixels changed to: left = %d, right = %d, top = %d, bottom = %d\n",
strut[0], strut[1], strut[2], strut[3]);
- win->reserved = (struct reservedpx) {strut[0], strut[1], strut[2], strut[3]};
+ win->reserved = (struct reservedpx){strut[0], strut[1], strut[2], strut[3]};
free(prop);
}
Rect *r = &(con->rect);
Rect *w = &(con->window_rect);
- p->con_rect = (struct width_height) {r->width, r->height};
- p->con_window_rect = (struct width_height) {w->width, w->height};
+ p->con_rect = (struct width_height){r->width, r->height};
+ p->con_window_rect = (struct width_height){w->width, w->height};
p->con_deco_rect = con->deco_rect;
p->background = config.client.background;
p->con_is_leaf = con_is_leaf(con);
);
#endif
- xcb_change_gc(conn, con->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {config.client.background});
+ xcb_change_gc(conn, con->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){config.client.background});
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, sizeof(background) / sizeof(xcb_rectangle_t), background);
}
* (left, bottom and right part). We don’t just fill the whole
* rectangle because some childs are not freely resizable and we want
* their background color to "shine through". */
- xcb_change_gc(conn, con->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->background});
+ xcb_change_gc(conn, con->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){p->color->background});
if (!(borders_to_hide & ADJ_LEFT_SCREEN_EDGE)) {
xcb_rectangle_t leftline = {0, 0, br.x, r->height};
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, &leftline);
if (TAILQ_NEXT(con, nodes) == NULL &&
TAILQ_PREV(con, nodes_head, nodes) == NULL &&
con->parent->type != CT_FLOATING_CON) {
- xcb_change_gc(conn, con->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->indicator});
+ xcb_change_gc(conn, con->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){p->color->indicator});
if (p->parent_layout == L_SPLITH)
- xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, (xcb_rectangle_t[]) {
+ xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, (xcb_rectangle_t[]){
{r->width + (br.width + br.x), br.y, -(br.width + br.x), r->height + br.height}});
else if (p->parent_layout == L_SPLITV)
- xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, (xcb_rectangle_t[]) {
+ xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, (xcb_rectangle_t[]){
{br.x, r->height + (br.height + br.y), r->width + br.width, -(br.height + br.y)}});
}
}
goto copy_pixmaps;
/* 4: paint the bar */
- xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->background});
+ xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){p->color->background});
xcb_rectangle_t drect = {con->deco_rect.x, con->deco_rect.y, con->deco_rect.width, con->deco_rect.height};
xcb_poly_fill_rectangle(conn, parent->pixmap, parent->pm_gc, 1, &drect);
/* 5: draw two unconnected horizontal lines in border color */
- xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->border});
+ xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){p->color->border});
Rect *dr = &(con->deco_rect);
adjacent_t borders_to_hide = con_adjacent_borders(con) & config.hide_edge_borders;
int deco_diff_l = borders_to_hide & ADJ_LEFT_SCREEN_EDGE ? 0 : con->current_border_width;
- int deco_diff_r = borders_to_hide & ADJ_RIGHT_SCREEN_EDGE ? 0 : con-> current_border_width;
+ int deco_diff_r = borders_to_hide & ADJ_RIGHT_SCREEN_EDGE ? 0 : con->current_border_width;
if (parent->layout == L_TABBED ||
(parent->layout == L_STACKED && TAILQ_NEXT(con, nodes) != NULL)) {
- deco_diff_l = 0;
- deco_diff_r = 0;
+ deco_diff_l = 0;
+ deco_diff_r = 0;
}
xcb_segment_t segments[] = {
{dr->x, dr->y,
/* Draw a 1px separator line before and after every tab, so that tabs can
* be easily distinguished. */
if (parent->layout == L_TABBED) {
- xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->border});
+ xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){p->color->border});
} else {
- xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->background});
+ xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){p->color->background});
}
xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, parent->pixmap, parent->pm_gc, 6,
- (xcb_point_t[]) {
+ (xcb_point_t[]){
{dr->x + dr->width, dr->y},
{dr->x + dr->width, dr->y + dr->height},
{dr->x + dr->width - 1, dr->y},
{dr->x, dr->y},
});
- xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]) {p->color->border});
+ xcb_change_gc(conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){p->color->border});
xcb_poly_segment(conn, parent->pixmap, parent->pm_gc, 2, segments);
copy_pixmaps:
Output *target = get_output_containing(mid_x, mid_y);
if (current != target) {
/* Ignore MotionNotify events generated by warping */
- xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]) {XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT});
+ xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT});
xcb_warp_pointer(conn, XCB_NONE, root, 0, 0, 0, 0, mid_x, mid_y);
- xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]) {ROOT_EVENT_MASK});
+ xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){ROOT_EVENT_MASK});
}
}
warp_to = NULL;
*/
void xcb_draw_line(xcb_connection_t *conn, xcb_drawable_t drawable, xcb_gcontext_t gc,
uint32_t colorpixel, uint32_t x, uint32_t y, uint32_t to_x, uint32_t to_y) {
- xcb_change_gc(conn, gc, XCB_GC_FOREGROUND, (uint32_t[]) {colorpixel});
+ xcb_change_gc(conn, gc, XCB_GC_FOREGROUND, (uint32_t[]){colorpixel});
xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, drawable, gc, 2,
- (xcb_point_t[]) {{x, y}, {to_x, to_y}});
+ (xcb_point_t[]){{x, y}, {to_x, to_y}});
}
/*
*/
void xcb_draw_rect(xcb_connection_t *conn, xcb_drawable_t drawable, xcb_gcontext_t gc,
uint32_t colorpixel, uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
- xcb_change_gc(conn, gc, XCB_GC_FOREGROUND, (uint32_t[]) {colorpixel});
+ xcb_change_gc(conn, gc, XCB_GC_FOREGROUND, (uint32_t[]){colorpixel});
xcb_rectangle_t rect = {x, y, width, height};
xcb_poly_fill_rectangle(conn, drawable, gc, 1, &rect);
}
*/
void xcursor_set_root_cursor(int cursor_id) {
xcb_change_window_attributes(conn, root, XCB_CW_CURSOR,
- (uint32_t[]) {xcursor_get_cursor(cursor_id)});
+ (uint32_t[]){xcursor_get_cursor(cursor_id)});
}
xcb_cursor_t xcursor_get_cursor(enum xcursor_cursor_t c) {
+++ /dev/null
-#!perl
-# vim:ts=4:sw=4:expandtab
-#
-# Please read the following documents before working on tests:
-# • http://build.i3wm.org/docs/testsuite.html
-# (or docs/testsuite)
-#
-# • http://build.i3wm.org/docs/lib-i3test.html
-# (alternatively: perldoc ./testcases/lib/i3test.pm)
-#
-# • http://build.i3wm.org/docs/ipc.html
-# (or docs/ipc)
-#
-# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
-# (unless you are already familiar with Perl)
-#
-# Correctly handle WM_CHANGE_STATE requests for the iconic state
-# See http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.4
-# Ticket: #1279
-# Bug still in: 4.8-7-gf4a8253
-use i3test;
-
-sub send_iconic_state_request {
- my ($win) = @_;
-
- my $msg = pack "CCSLLLLLL",
- X11::XCB::CLIENT_MESSAGE, # response_type
- 32, # format
- 0, # sequence
- $win->id, # window
- $x->atom(name => 'WM_CHANGE_STATE')->id, # message type
- 3, # data32[0]
- 0, # data32[1]
- 0, # data32[2]
- 0, # data32[3]
- 0; # data32[4]
-
- $x->send_event(0, $x->get_root_window(), X11::XCB::EVENT_MASK_SUBSTRUCTURE_REDIRECT, $msg);
-}
-
-my $ws = fresh_workspace;
-my $win = open_window;
-
-send_iconic_state_request($win);
-sync_with_i3;
-
-is(@{get_ws($ws)->{nodes}}, 0, 'When a window requests the iconic state, the container should be closed');
-
-done_testing;