void focus_node(monitor_t *m, desktop_t *d, node_t *n, bool is_mapped) { if (n == NULL) return; PRINTF("focus node %X\n", n->client->window); split_mode = MODE_AUTOMATIC; n->client->urgent = false; if (is_mapped) { if (mon != m) { for (desktop_t *cd = mon->desk_head; cd != NULL; cd = cd->next) window_draw_border(cd->focus, true, false); for (desktop_t *cd = m->desk_head; cd != NULL; cd = cd->next) if (cd != d) window_draw_border(cd->focus, true, true); if (d->focus == n) window_draw_border(n, true, true); } if (d->focus != n) { window_draw_border(d->focus, false, true); window_draw_border(n, true, true); } xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, n->client->window, XCB_CURRENT_TIME); } if (focus_follows_pointer) { xcb_window_t win = XCB_NONE; get_pointed_window(&win); if (win != n->client->window) enable_motion_recorder(); else disable_motion_recorder(); } if (!is_tiled(n->client)) { if (!adaptative_raise || !might_cover(d, n)) window_raise(n->client->window); } else { window_pseudo_raise(d, n->client->window); } if (d->focus != n) { d->last_focus = d->focus; d->focus = n; } ewmh_update_active_window(); put_status(); }
void gui_update_playlist(void) { window_draw_border(playlist_window); window_draw_title(playlist_window); window_draw_scrollbar(playlist_window); window_draw_list(playlist_window); window_update(playlist_window); }
void draw_border(node_t *n, bool focused_node, bool focused_monitor) { if (n == NULL) { return; } uint32_t border_color_pxl = get_border_color(focused_node, focused_monitor); for (node_t *f = first_extrema(n); f != NULL; f = next_leaf(f, n)) { if (f->client->border_width > 0) { window_draw_border(f->id, border_color_pxl); } } }
void gui_update_filelist(void) { if(!filelist_window){ return; } window_draw_border(filelist_window); window_draw_title(filelist_window); window_draw_scrollbar(filelist_window); window_draw_list(filelist_window); window_update(filelist_window); //Update the info window as we are updated as well gui_update_info(); gui_update(); }
/* * Rearrange left and right child of a given pair, based on method and sized * already set in the (as usually) right window. */ void window_rearrange(winid_t pair) { SDL_Rect left_area, right_area; window_calc_sizes(pair, &left_area, &right_area); // Let the window resize first, which size has been reduced, so that it can // copy from the old area before the now larger window will overwrite it. int or = pair->right->method & winmethod_DirMask; if(((or == winmethod_Above || or == winmethod_Below) && left_area.h < pair->left->area.h) || ((or == winmethod_Left || or == winmethod_Right) && left_area.w < pair->left->area.w)) { window_resize(pair->left, &left_area); window_resize(pair->right, &right_area); } else { window_resize(pair->right, &right_area); window_resize(pair->left, &left_area); } window_draw_border(pair); }
void track_pointer(int root_x, int root_y) { if (frozen_pointer->action == ACTION_NONE) return; int16_t delta_x, delta_y, x = 0, y = 0, w = 1, h = 1; uint16_t width, height; pointer_action_t pac = frozen_pointer->action; monitor_t *m = frozen_pointer->monitor; desktop_t *d = frozen_pointer->desktop; node_t *n = frozen_pointer->node; client_t *c = frozen_pointer->client; xcb_window_t win = frozen_pointer->window; xcb_rectangle_t rect = frozen_pointer->rectangle; node_t *vertical_fence = frozen_pointer->vertical_fence; node_t *horizontal_fence = frozen_pointer->horizontal_fence; delta_x = root_x - frozen_pointer->position.x; delta_y = root_y - frozen_pointer->position.y; switch (pac) { case ACTION_MOVE: if (frozen_pointer->is_tiled) { xcb_window_t pwin = XCB_NONE; query_pointer(&pwin, NULL); if (pwin == win) return; coordinates_t loc; bool is_managed = (pwin == XCB_NONE ? false : locate_window(pwin, &loc)); if (is_managed && is_tiled(loc.node->client) && loc.monitor == m) { swap_nodes(m, d, n, m, d, loc.node); arrange(m, d); } else { if (is_managed && loc.monitor == m) { return; } else if (!is_managed) { xcb_point_t pt = (xcb_point_t) {root_x, root_y}; monitor_t *pmon = monitor_from_point(pt); if (pmon == NULL || pmon == m) { return; } else { loc.monitor = pmon; loc.desktop = pmon->desk; } } bool focused = (n == mon->desk->focus); transfer_node(m, d, n, loc.monitor, loc.desktop, loc.desktop->focus); if (focused) focus_node(loc.monitor, loc.desktop, n); frozen_pointer->monitor = loc.monitor; frozen_pointer->desktop = loc.desktop; } } else { x = rect.x + delta_x; y = rect.y + delta_y; window_move(win, x, y); c->floating_rectangle.x = x; c->floating_rectangle.y = y; xcb_point_t pt = (xcb_point_t) {root_x, root_y}; monitor_t *pmon = monitor_from_point(pt); if (pmon == NULL || pmon == m) return; bool focused = (n == mon->desk->focus); transfer_node(m, d, n, pmon, pmon->desk, pmon->desk->focus); if (focused) focus_node(pmon, pmon->desk, n); frozen_pointer->monitor = pmon; frozen_pointer->desktop = pmon->desk; } break; case ACTION_RESIZE_SIDE: case ACTION_RESIZE_CORNER: if (frozen_pointer->is_tiled) { if (vertical_fence != NULL) { double sr = frozen_pointer->vertical_ratio + (double) delta_x / vertical_fence->rectangle.width; sr = MAX(0, sr); sr = MIN(1, sr); vertical_fence->split_ratio = sr; } if (horizontal_fence != NULL) { double sr = frozen_pointer->horizontal_ratio + (double) delta_y / horizontal_fence->rectangle.height; sr = MAX(0, sr); sr = MIN(1, sr); horizontal_fence->split_ratio = sr; } arrange(mon, mon->desk); } else { if (pac == ACTION_RESIZE_SIDE) { switch (frozen_pointer->side) { case SIDE_TOP: x = rect.x; y = rect.y + delta_y; w = rect.width; h = rect.height - delta_y; break; case SIDE_RIGHT: x = rect.x; y = rect.y; w = rect.width + delta_x; h = rect.height; break; case SIDE_BOTTOM: x = rect.x; y = rect.y; w = rect.width; h = rect.height + delta_y; break; case SIDE_LEFT: x = rect.x + delta_x; y = rect.y; w = rect.width - delta_x; h = rect.height; break; } width = MAX(1, w); height = MAX(1, h); window_move_resize(win, x, y, width, height); c->floating_rectangle = (xcb_rectangle_t) {x, y, width, height}; window_draw_border(n, d->focus == n, mon == m); } else if (pac == ACTION_RESIZE_CORNER) { switch (frozen_pointer->corner) { case CORNER_TOP_LEFT: x = rect.x + delta_x; y = rect.y + delta_y; w = rect.width - delta_x; h = rect.height - delta_y; break; case CORNER_TOP_RIGHT: x = rect.x; y = rect.y + delta_y; w = rect.width + delta_x; h = rect.height - delta_y; break; case CORNER_BOTTOM_LEFT: x = rect.x + delta_x; y = rect.y; w = rect.width - delta_x; h = rect.height + delta_y; break; case CORNER_BOTTOM_RIGHT: x = rect.x; y = rect.y; w = rect.width + delta_x; h = rect.height + delta_y; break; } width = MAX(1, w); height = MAX(1, h); window_move_resize(win, x, y, width, height); c->floating_rectangle = (xcb_rectangle_t) {x, y, width, height}; window_draw_border(n, d->focus == n, mon == m); } } break; case ACTION_FOCUS: case ACTION_NONE: break; } }
void apply_layout(monitor_t *m, desktop_t *d, node_t *n, xcb_rectangle_t rect, xcb_rectangle_t root_rect) { if (n == NULL) return; n->rectangle = rect; if (is_leaf(n)) { if (n->client->fullscreen) return; if (is_floating(n->client) && n->client->border_width != border_width) { int ds = 2 * (border_width - n->client->border_width); n->client->floating_rectangle.width += ds; n->client->floating_rectangle.height += ds; } if (borderless_monocle && is_tiled(n->client) && d->layout == LAYOUT_MONOCLE) n->client->border_width = 0; else n->client->border_width = border_width; xcb_rectangle_t r; if (is_tiled(n->client)) { if (d->layout == LAYOUT_TILED) r = rect; else if (d->layout == LAYOUT_MONOCLE) r = root_rect; int wg = (gapless_monocle && d->layout == LAYOUT_MONOCLE ? 0 : window_gap); int bleed = wg + 2 * n->client->border_width; r.width = (bleed < r.width ? r.width - bleed : 1); r.height = (bleed < r.height ? r.height - bleed : 1); n->client->tiled_rectangle = r; } else { r = n->client->floating_rectangle; } window_move_resize(n->client->window, r.x, r.y, r.width, r.height); window_border_width(n->client->window, n->client->border_width); window_draw_border(n, n == d->focus, m == mon); } else { xcb_rectangle_t first_rect; xcb_rectangle_t second_rect; if (n->first_child->vacant || n->second_child->vacant) { first_rect = second_rect = rect; } else { unsigned int fence; if (n->split_type == TYPE_VERTICAL) { fence = rect.width * n->split_ratio; first_rect = (xcb_rectangle_t) {rect.x, rect.y, fence, rect.height}; second_rect = (xcb_rectangle_t) {rect.x + fence, rect.y, rect.width - fence, rect.height}; } else if (n->split_type == TYPE_HORIZONTAL) { fence = rect.height * n->split_ratio; first_rect = (xcb_rectangle_t) {rect.x, rect.y, rect.width, fence}; second_rect = (xcb_rectangle_t) {rect.x, rect.y + fence, rect.width, rect.height - fence}; } } apply_layout(m, d, n->first_child, first_rect, root_rect); apply_layout(m, d, n->second_child, second_rect, root_rect); } }
winid_t glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype, glui32 rock) { winid_t win = (winid_t)nano_malloc(sizeof(struct glk_window_struct)); nanoglk_log("glk_window_open(%p, %d, %d, %d, %d) => %p", split, method, size, wintype, rock, win); win->stream = nanoglk_stream_new(streamtype_Window, 0); win->stream->x.window = win; win->method = method; win->size = size; win->wintype = wintype; win->rock = rock; win->left = win->right = NULL; win->cur_styl = style_Normal; // Colors for styles. See comment at the beginning of this file. int i; switch(win->wintype) { case wintype_TextBuffer: for(i = 0; i < style_NUMSTYLES; i++) { win->fg[i] = next_buffer_fg[i]; win->bg[i] = next_buffer_bg[i]; } break; case wintype_TextGrid: for(i = 0; i < style_NUMSTYLES; i++) { win->fg[i] = next_grid_fg[i]; win->bg[i] = next_grid_bg[i]; } break; } winid_t pair; if(split == NULL) { // parent is NULL => new root window nano_failunless(root == NULL, "two root windows"); win->parent = NULL; win->area.x = win->area.y = 0; win->area.w = nanoglk_surface->w; win->area.h = nanoglk_surface->h; root = win; pair = NULL; // no pair window created nano_trace("[glk_window_open] root %p: (%d, %d, %d x %d)", win, win->area.x, win->area.y, win->area.w, win->area.h); } else { // Create a pair window. The old parent "split" becomes the left // child, the newly created becomes the right child. (See also // comment on these members in "nanoglk.h".) pair = (winid_t)nano_malloc(sizeof(struct glk_window_struct)); pair->stream = NULL; pair->wintype = wintype_Pair; pair->rock = 0; pair->left = split; pair->right = win; pair->area = split->area; pair->method = split->method; pair->size = split->size; pair->parent = split->parent; // Rearrange tree: "pair" takes over the place of "split". if(pair->parent == NULL) root = pair; else { if(pair->parent->left == split) pair->parent->left = pair; else if(pair->parent->right == split) pair->parent->right = pair; else nano_fail("split not child of parent?"); } split->parent = win->parent = pair; pair->left = split; pair->right = win; win->area = split->area; SDL_Rect split_area, win_area; window_calc_sizes(pair, &split_area, &win_area); window_resize(split, &split_area); win->area = win_area; window_draw_border(pair); nano_trace("split %p: (%d, %d, %d x %d)", split, split->area.x, split->area.y, split->area.w, split->area.h); nano_trace("new win %p: (%d, %d, %d x %d)", win, win->area.x, win->area.y, win->area.w, win->area.h); } // Further initialization depending on the type. switch(win->wintype) { case wintype_TextBuffer: nanoglk_wintextbuffer_init(win); break; case wintype_TextGrid: nanoglk_wintextgrid_init(win); break; case wintype_Graphics: nanoglk_wingraphics_init(win); break; } if(pair) pair->disprock = nanoglk_call_regi_obj(pair, gidisp_Class_Window); win->stream->disprock = nanoglk_call_regi_obj(win->stream, gidisp_Class_Stream); win->disprock = nanoglk_call_regi_obj(win, gidisp_Class_Window); return win; }