diff --git a/include/commands.h b/include/commands.h index a2701924..b060cd10 100644 --- a/include/commands.h +++ b/include/commands.h @@ -14,7 +14,11 @@ #define _COMMANDS_H bool focus_window_in_container(xcb_connection_t *conn, Container *container, direction_t direction); + +/** Switches to the given workspace */ void show_workspace(xcb_connection_t *conn, int workspace); + +/** Parses a command, see file CMDMODE for more information */ void parse_command(xcb_connection_t *conn, const char *command); #endif diff --git a/include/config.h b/include/config.h index 4aa0192b..59c6866f 100644 --- a/include/config.h +++ b/include/config.h @@ -9,6 +9,13 @@ struct Config { const char *font; }; +/** + * Reads the configuration from ~/.i3/config or /etc/i3/config if not found. + * + * If you specify override_configpath, only this path is used to look for a + * configuration file. + * + */ void load_configuration(const char *override_configfile); #endif diff --git a/include/handlers.h b/include/handlers.h index e10a0089..b2c0de94 100644 --- a/include/handlers.h +++ b/include/handlers.h @@ -11,22 +11,108 @@ #ifndef _HANDLERS_H #define _HANDLERS_H +/** + * Due to bindings like Mode_switch + , we need to bind some keys in XCB_GRAB_MODE_SYNC. + * Therefore, we just replay all key presses. + * + */ int handle_key_release(void *ignored, xcb_connection_t *conn, xcb_key_release_event_t *event); + +/** + * There was a key press. We compare this key code with our bindings table and pass + * the bound action to parse_command(). + * + */ int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press_event_t *event); + +/** + * When the user moves the mouse pointer onto a window, this callback gets called. + * + */ int handle_enter_notify(void *ignored, xcb_connection_t *conn, xcb_enter_notify_event_t *event); + +/** + * Checks if the button press was on a stack window, handles focus setting and returns true + * if so, or false otherwise. + * + */ int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_event_t *event); + +/** + * A new window appeared on the screen (=was mapped), so let’s manage it. + * + */ int handle_map_request(void *prophs, xcb_connection_t *conn, xcb_map_request_event_t *event); + +/** + * Configuration notifies are only handled because we need to set up ignore for the following + * enter notify events + * + */ int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_notify_event_t *event); + +/** + * Configure requests are received when the application wants to resize windows on their own. + * + * We generate a synthethic configure notify event to signalize the client its "new" position. + * + */ int handle_configure_request(void *prophs, xcb_connection_t *conn, xcb_configure_request_event_t *event); + +/** + * Our window decorations were unmapped. That means, the window will be killed now, + * so we better clean up before. + * + */ int handle_unmap_notify_event(void *data, xcb_connection_t *conn, xcb_unmap_notify_event_t *event); + +/** + * Called when a window changes its title + * + */ int handle_windowname_change(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop); + +/** + * We handle legacy window names (titles) which are in COMPOUND_TEXT encoding. However, we + * just pass them along, so when containing non-ASCII characters, those will be rendering + * incorrectly. In order to correctly render unicode window titles in i3, an application + * has to set _NET_WM_NAME, which is in UTF-8 encoding. + * + * On every update, a message is put out to the user, so he may improve the situation and + * update applications which display filenames in their title to correctly use + * _NET_WM_NAME and therefore support unicode. + * + */ int handle_windowname_change_legacy(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop); + +/** + * Expose event means we should redraw our windows (= title bar) + * + */ int handle_expose_event(void *data, xcb_connection_t *conn, xcb_expose_event_t *event); + +/** + * Handle client messages (EWMH) + * + */ int handle_client_message(void *data, xcb_connection_t *conn, xcb_client_message_event_t *event); + +/** + * Handles _NET_WM_WINDOW_TYPE changes + * + */ int handle_window_type(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *property); + +/** + * Handles the size hints set by a window, but currently only the part necessary for displaying + * clients proportionally inside their frames (mplayer for example) + * + * See ICCCM 4.1.2.3 for more details + * + */ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, xcb_atom_t name, xcb_get_property_reply_t *reply); diff --git a/include/layout.h b/include/layout.h index ca90391c..7f930160 100644 --- a/include/layout.h +++ b/include/layout.h @@ -13,11 +13,44 @@ #ifndef _LAYOUT_H #define _LAYOUT_H -Rect get_unoccupied_space(Workspace *workspace); +/** + * (Re-)draws window decorations for a given Client onto the given drawable/graphic context. + * When in stacking mode, the window decorations are drawn onto an own window. + * + */ void decorate_window(xcb_connection_t *conn, Client *client, xcb_drawable_t drawable, xcb_gcontext_t gc, int offset); + +/** + * Redecorates the given client correctly by checking if it’s in a stacking container and + * re-rendering the stack window or just calling decorate_window if it’s not in a stacking + * container. + * + */ void redecorate_window(xcb_connection_t *conn, Client *client); + +/** + * Renders the given container. Is called by render_layout() or individually (for example + * when focus changes in a stacking container) + * + */ void render_container(xcb_connection_t *conn, Container *container); + +/** + * Modifies the event mask of all clients on the given workspace to either ignore or to handle + * enter notifies. It is handy to ignore notifies because they will be sent when a window is mapped + * under the cursor, thus when the user didn’t enter the window actively at all. + * + */ void ignore_enter_notify_forall(xcb_connection_t *conn, Workspace *workspace, bool ignore_enter_notify); + +/** + * Renders the whole layout, that is: Go through each screen, each workspace, each container + * and render each client. This also renders the bars. + * + * If you don’t need to render *everything*, you should call render_container on the container + * you want to refresh. + * + */ void render_layout(xcb_connection_t *conn); #endif diff --git a/include/table.h b/include/table.h index 5db1cda4..de83c7d0 100644 --- a/include/table.h +++ b/include/table.h @@ -25,14 +25,31 @@ extern Workspace workspaces[10]; extern int current_col; extern int current_row; +/** Initialize table */ void init_table(); + +/** Add one row to the table */ void expand_table_rows(Workspace *workspace); + +/** Adds one row at the head of the table */ void expand_table_rows_at_head(Workspace *workspace); + +/** Add one column to the table */ void expand_table_cols(Workspace *workspace); + +/** Inserts one column at the table’s head */ void expand_table_cols_at_head(Workspace *workspace); + +/** Performs simple bounds checking for the given column/row */ bool cell_exists(int col, int row); + +/** Shrinks the table by "compacting" it, that is, removing completely empty rows/columns */ void cleanup_table(xcb_connection_t *conn, Workspace *workspace); + +/** Fixes col/rowspan (makes sure there are no overlapping windows) */ void fix_colrowspan(xcb_connection_t *conn, Workspace *workspace); + +/** Prints the table’s contents in human-readable form for debugging */ void dump_table(xcb_connection_t *conn, Workspace *workspace); #endif diff --git a/include/util.h b/include/util.h index eb126354..b575e3fc 100644 --- a/include/util.h +++ b/include/util.h @@ -39,20 +39,116 @@ while (0) int min(int a, int b); int max(int a, int b); + +/** + * Logs the given message to stdout while prefixing the current time to it. + * This is to be called by LOG() which includes filename/linenumber + * + */ void slog(char *fmt, ...); + +/** + * Prints the message (see printf()) to stderr, then exits the program. + * + */ void die(char *fmt, ...); + +/** + * Safe-wrapper around malloc which exits if malloc returns NULL (meaning that there + * is no more memory available) + * + */ void *smalloc(size_t size); + +/** + * Safe-wrapper around calloc which exits if malloc returns NULL (meaning that there + * is no more memory available) + * + */ void *scalloc(size_t size); + +/** + * Safe-wrapper around strdup which exits if malloc returns NULL (meaning that there + * is no more memory available) + * + */ char *sstrdup(const char *str); + +/** + * Starts the given application by passing it through a shell. We use double fork + * to avoid zombie processes. As the started application’s parent exits (immediately), + * the application is reparented to init (process-id 1), which correctly handles + * childs, so we don’t have to do it :-). + * + * The shell is determined by looking for the SHELL environment variable. If it + * does not exist, /bin/sh is used. + * + */ void start_application(const char *command); + +/** + * Checks a generic cookie for errors and quits with the given message if there + * was an error. + * + */ void check_error(xcb_connection_t *conn, xcb_void_cookie_t cookie, char *err_message); + +/** + * Converts the given string to UCS-2 big endian for use with + * xcb_image_text_16(). The amount of real glyphs is stored in real_strlen, + * a buffer containing the UCS-2 encoded string (16 bit per glyph) is + * returned. It has to be freed when done. + * + */ char *convert_utf8_to_ucs2(char *input, int *real_strlen); + +/** + * Removes the given client from the container, either because it will be inserted into another + * one or because it was unmapped + * + */ void remove_client_from_container(xcb_connection_t *conn, Client *client, Container *container); + +/** + * Sets the given client as focused by updating the data structures correctly, + * updating the X input focus and finally re-decorating both windows (to signalize + * the user the new focus situation) + * + */ void set_focus(xcb_connection_t *conn, Client *client, bool set_anyways); + +/** + * Called when the user switches to another mode or when the container is + * destroyed and thus needs to be cleaned up. + * + */ void leave_stack_mode(xcb_connection_t *conn, Container *container); + +/** + * Switches the layout of the given container taking care of the necessary house-keeping + * + */ void switch_layout_mode(xcb_connection_t *conn, Container *container, int mode); + +/** + * Warps the pointer into the given client (in the middle of it, to be specific), therefore + * selecting it + * + */ void warp_pointer_into(xcb_connection_t *conn, Client *client); + +/** + * Toggles fullscreen mode for the given client. It updates the data structures and + * reconfigures (= resizes/moves) the client and its frame to the full size of the + * screen. When leaving fullscreen, re-rendering the layout is forced. + * + */ void toggle_fullscreen(xcb_connection_t *conn, Client *client); + +/** + * Kills the given window using WM_DELETE_WINDOW or xcb_kill_window + * + */ void kill_window(xcb_connection_t *conn, Client *window); #endif diff --git a/include/xcb.h b/include/xcb.h index 7ba80867..83069e45 100644 --- a/include/xcb.h +++ b/include/xcb.h @@ -56,16 +56,64 @@ enum { _NET_SUPPORTED = 0, extern unsigned int xcb_numlock_mask; +/** + * Loads a font for usage, getting its height. This function is used very often, so it + * maintains a cache. + * + */ i3Font *load_font(xcb_connection_t *conn, const char *pattern); + +/** + * Returns the colorpixel to use for the given hex color (think of HTML). + * + * The hex_color has to start with #, for example #FF00FF. + * + * NOTE that get_colorpixel() does _NOT_ check the given color code for validity. + * This has to be done by the caller. + * + */ uint32_t get_colorpixel(xcb_connection_t *conn, char *hex); + +/** + * Convenience wrapper around xcb_create_window which takes care of depth, generating an ID and checking + * for errors. + * + */ xcb_window_t create_window(xcb_connection_t *conn, Rect r, uint16_t window_class, int cursor, uint32_t mask, uint32_t *values); + +/** + * Changes a single value in the graphic context (so one doesn’t have to define an array of values) + * + */ void xcb_change_gc_single(xcb_connection_t *conn, xcb_gcontext_t gc, uint32_t mask, uint32_t value); + +/** + * Draws a line from x,y to to_x,to_y using the given color + * + */ 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); + +/** + * Draws a rectangle from x,y with width,height using the given color + * + */ 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); + +/** + * Generates a configure_notify event and sends it to the given window + * Applications need this to think they’ve configured themselves correctly. + * The truth is, however, that we will manage them. + * + */ void fake_configure_notify(xcb_connection_t *conn, Rect r, xcb_window_t window); + +/** + * Finds out which modifier mask is the one for numlock, as the user may change this. + * + */ void xcb_get_numlock_mask(xcb_connection_t *conn); #endif diff --git a/include/xinerama.h b/include/xinerama.h index b8a591c1..a1ae70bf 100644 --- a/include/xinerama.h +++ b/include/xinerama.h @@ -16,10 +16,40 @@ TAILQ_HEAD(screens_head, Screen); extern struct screens_head *virtual_screens; +/** + * We have just established a connection to the X server and need the initial Xinerama + * information to setup workspaces for each screen. + * + */ void initialize_xinerama(xcb_connection_t *conn); + +/** + * This is called when the rootwindow receives a configure_notify event and therefore the + * number/position of the Xinerama screens could have changed. + * + */ void xinerama_requery_screens(xcb_connection_t *conn); + +/** + * Looks in virtual_screens for the i3Screen whose start coordinates are x, y + * + */ i3Screen *get_screen_at(int x, int y, struct screens_head *screenlist); + +/** + * Looks in virtual_screens for the i3Screen which contains coordinates x, y + * + */ i3Screen *get_screen_containing(int x, int y); + +/** + * Gets the screen which is the last one in the given direction, for example the screen + * on the most bottom when direction == D_DOWN, the screen most right when direction == D_RIGHT + * and so on. + * + * This function always returns a screen. + * + */ i3Screen *get_screen_most(direction_t direction); #endif diff --git a/pseudo-doc.doxygen b/pseudo-doc.doxygen new file mode 100644 index 00000000..e8e7b3e2 --- /dev/null +++ b/pseudo-doc.doxygen @@ -0,0 +1,148 @@ +# Doxyfile 1.5.6 +# +# You can use this file with doxygen to create a pseudo-documentation +# automatically from source. doxygen-comments are not used very extensively +# in i3, mostly for the reason that it clutters the source code and has no +# real use (doxygen’s output looks really ugly). +# +# So, if you want to use it, here you go. This is however not a supported +# document, and I recommend you have a look at the docs/ folder or at +# http://i3.zekjur.net/ for more, real documentation. +# + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = i3 +PROJECT_NUMBER = +OUTPUT_DIRECTORY = pseudo-doc +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = YES +FULL_PATH_NAMES = YES +SHORT_NAMES = YES +JAVADOC_AUTOBRIEF = YES +TAB_SIZE = 8 +OPTIMIZE_OUTPUT_FOR_C = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +EXTRACT_ALL = YES +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = YES +CASE_SENSE_NAMES = YES +SHOW_INCLUDE_FILES = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +SHOW_USED_FILES = YES +SHOW_FILES = YES + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +INPUT = src include +INPUT_ENCODING = UTF-8 +RECURSIVE = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +SOURCE_BROWSER = YES +INLINE_SOURCES = NO + +STRIP_CODE_COMMENTS = YES + +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +REFERENCES_LINK_SOURCE = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_ALIGN_MEMBERS = YES +HTML_DYNAMIC_SECTIONS = NO +FORMULA_FONTSIZE = 10 + +GENERATE_LATEX = NO +GENERATE_RTF = NO +GENERATE_MAN = NO +GENERATE_XML = NO +GENERATE_AUTOGEN_DEF = NO +GENERATE_PERLMOD = NO + +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +CLASS_DIAGRAMS = YES +HAVE_DOT = YES +DOT_FONTNAME = FreeSans +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = YES +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = YES +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +SEARCHENGINE = NO diff --git a/src/layout.c b/src/layout.c index 9d9a0927..153d0454 100644 --- a/src/layout.c +++ b/src/layout.c @@ -485,6 +485,14 @@ void ignore_enter_notify_forall(xcb_connection_t *conn, Workspace *workspace, bo } } +/* + * Renders the whole layout, that is: Go through each screen, each workspace, each container + * and render each client. This also renders the bars. + * + * If you don’t need to render *everything*, you should call render_container on the container + * you want to refresh. + * + */ void render_layout(xcb_connection_t *conn) { i3Screen *screen; i3Font *font = load_font(conn, config.font); diff --git a/src/table.c b/src/table.c index 791362ed..222ebdcc 100644 --- a/src/table.c +++ b/src/table.c @@ -211,6 +211,10 @@ static void move_rows_from(xcb_connection_t *conn, Workspace *workspace, int row } } +/* + * Prints the table’s contents in human-readable form for debugging + * + */ void dump_table(xcb_connection_t *conn, Workspace *workspace) { LOG("dump_table()\n"); FOR_TABLE(workspace) {