diff --git a/src/bar.c b/src/bar.c index 9224057..7854743 100644 --- a/src/bar.c +++ b/src/bar.c @@ -12,17 +12,24 @@ void bar_draw_graph(struct bar* bar, struct bar_item* bar_item, uint32_t x, bool bool bar_draws_item(struct bar* bar, struct bar_item* bar_item) { if (!bar_item->drawing || !bar->shown || bar->hidden) return false; + if (bar_item->associated_display > 0 && (!(bar_item->associated_display & (1 << bar->adid))) && !bar_item->ignore_association) return false; + if (bar_item->associated_space > 0 && (!(bar_item->associated_space & (1 << bar->sid)) && !bar_item->ignore_association) && (bar_item->type != BAR_COMPONENT_SPACE) ) return false; - if (bar_item->position == POSITION_POPUP) + + if (bar_item->position == POSITION_POPUP + && (!bar_item->parent + || !bar_item->parent->popup.drawing + || (bar->adid != g_bar_manager.active_adid))) return false; + return true; } @@ -32,7 +39,6 @@ void bar_calculate_popup_anchor_for_bar_item(struct bar* bar, struct bar_item* b if (!bar_item->popup.overrides_cell_size) bar_item->popup.cell_size = window->frame.size.height; - bool needs_recalculation = bar_item->popup.adid != bar->adid; popup_calculate_bounds(&bar_item->popup); CGPoint anchor = window->origin; @@ -50,9 +56,7 @@ void bar_calculate_popup_anchor_for_bar_item(struct bar* bar, struct bar_item* b : window->frame.size.height); popup_set_anchor(&bar_item->popup, anchor, bar->adid); - if (needs_recalculation) { - popup_calculate_bounds(&bar_item->popup); - } + popup_calculate_bounds(&bar_item->popup); } void bar_order_item_windows(struct bar* bar, int mode) { @@ -61,9 +65,11 @@ void bar_order_item_windows(struct bar* bar, int mode) { struct window* previous_window = NULL; for (int i = 0; i < g_bar_manager.bar_item_count; i++) { struct bar_item* bar_item = g_bar_manager.bar_items[i]; + if (bar_item->position == POSITION_POPUP) continue; struct window* window = bar_item_get_window(bar_item, bar->adid); SLSRemoveFromOrderingGroup(g_connection, window->id); + window_set_level(window, g_bar_manager.window_level); if (bar_item->type == BAR_COMPONENT_GROUP) { @@ -112,11 +118,6 @@ void bar_draw(struct bar* bar) { for (int i = 0; i < g_bar_manager.bar_item_count; i++) { struct bar_item* bar_item = g_bar_manager.bar_items[i]; - - if (bar_item->position == POSITION_POPUP) { - continue; - } - struct window* window = bar_item_get_window(bar_item, bar->adid); bar_item_remove_associated_bar(bar_item, bar->adid); @@ -186,7 +187,8 @@ void bar_calculate_bounds(struct bar* bar) { struct bar_item* bar_item = g_bar_manager.bar_items[i]; if (!bar_draws_item(bar, bar_item) - || bar_item->type == BAR_COMPONENT_GROUP) { + || bar_item->type == BAR_COMPONENT_GROUP + || bar_item->position == POSITION_POPUP ) { continue; } @@ -203,8 +205,7 @@ void bar_calculate_bounds(struct bar* bar) { next_position = &bar_center_right_first_item_x; else if (bar_item->position == POSITION_CENTER_LEFT) next_position = &bar_center_left_first_item_x, rtl = true; - else - continue; + else continue; if (bar_item->position == POSITION_RIGHT || bar_item->position == POSITION_CENTER_LEFT) { diff --git a/src/bar_item.c b/src/bar_item.c index 7ca2a91..954cca9 100644 --- a/src/bar_item.c +++ b/src/bar_item.c @@ -15,6 +15,7 @@ void bar_item_clear_pointers(struct bar_item* bar_item) { bar_item->signal_args.env_vars.vars = NULL; bar_item->signal_args.env_vars.count = 0; bar_item->windows = NULL; + bar_item->popup.host = bar_item; bar_item->num_windows = 0; text_clear_pointers(&bar_item->icon); text_clear_pointers(&bar_item->label); @@ -93,8 +94,6 @@ void bar_item_init(struct bar_item* bar_item, struct bar_item* default_item) { bar_item->custom_width = 0; bar_item->y_offset = 0; - bar_item->group = NULL; - bar_item->has_alias = false; bar_item->has_graph = false; @@ -103,11 +102,14 @@ void bar_item_init(struct bar_item* bar_item, struct bar_item* default_item) { bar_item->script = NULL; bar_item->click_script = NULL; + bar_item->group = NULL; + bar_item->parent = NULL; + text_init(&bar_item->icon); text_init(&bar_item->label); background_init(&bar_item->background); env_vars_init(&bar_item->signal_args.env_vars); - popup_init(&bar_item->popup); + popup_init(&bar_item->popup, bar_item); graph_init(&bar_item->graph); alias_init(&bar_item->alias); @@ -450,15 +452,6 @@ CGRect bar_item_construct_bounding_rect(struct bar_item* bar_item) { return bounding_rect; } -void bar_item_set_bounding_rect_for_display(struct bar_item* bar_item, uint32_t adid, CGPoint bar_origin, uint32_t height) { - if (adid <= 0) return; - CGRect rect = CGRectInset(bar_item_construct_bounding_rect(bar_item), -1,-1); - struct window* window = bar_item_get_window(bar_item, adid); - window->origin.x = rect.origin.x + bar_origin.x; - window->origin.y = -rect.origin.y - rect.size.height + bar_origin.y + height; - window->frame.size = rect.size; -} - uint32_t bar_item_calculate_bounds(struct bar_item* bar_item, uint32_t bar_height, uint32_t x, uint32_t y) { uint32_t content_x = x; uint32_t content_y = y; @@ -776,7 +769,9 @@ void bar_item_parse_set_message(struct bar_item* bar_item, char* message, FILE* } struct bar_item* target_item = g_bar_manager.bar_items[item_index_for_name]; popup_add_item(&target_item->popup, bar_item); - } + } else { + bar_item->parent = NULL; + } } needs_refresh = true; } else if (token_equals(property, PROPERTY_ALIGN)) { diff --git a/src/bar_item.h b/src/bar_item.h index c19e980..6cba7a3 100644 --- a/src/bar_item.h +++ b/src/bar_item.h @@ -72,6 +72,7 @@ struct bar_item { // Popup struct popup popup; + struct bar_item* parent; }; struct bar_item* bar_item_create(); @@ -108,7 +109,6 @@ void bar_item_mouse_exited(struct bar_item* bar_item); struct window* bar_item_get_window(struct bar_item* bar_item, uint32_t adid); void bar_item_remove_window(struct bar_item* bar_item, uint32_t adid); CGRect bar_item_construct_bounding_rect(struct bar_item* bar_item); -void bar_item_set_bounding_rect_for_display(struct bar_item* bar_item, uint32_t adid, CGPoint bar_origin, uint32_t height); uint32_t bar_item_calculate_bounds(struct bar_item* bar_item, uint32_t bar_height, uint32_t x, uint32_t y); void bar_item_draw(struct bar_item* bar_item, CGContextRef context); diff --git a/src/bar_manager.c b/src/bar_manager.c index 5c7e218..1b38eb1 100644 --- a/src/bar_manager.c +++ b/src/bar_manager.c @@ -293,13 +293,8 @@ bool bar_manager_bar_needs_redraw(struct bar_manager* bar_manager, struct bar* b for (int i = 0; i < bar_manager->bar_item_count; i++) { struct bar_item* bar_item = bar_manager->bar_items[i]; - bool is_associated_space_shown = (bar_item->associated_space & (1 << bar->sid)) - || bar_item->associated_space == 0; - bool is_associated_display_shown = (bar_item->associated_display & (1 << bar->adid)); - if ((bar_item->drawing || (!bar_item->drawing - && bar_item->associated_bar != 0)) - && bar_item->needs_update && (is_associated_space_shown - || is_associated_display_shown)) { + if ((bar_item->needs_update && bar_draws_item(bar, bar_item)) + || (!bar_item->drawing && bar_item->associated_bar != 0) ) { return true; } } diff --git a/src/message.c b/src/message.c index dec099b..c0dd51d 100644 --- a/src/message.c +++ b/src/message.c @@ -149,6 +149,23 @@ static void handle_domain_add(FILE* rsp, struct token domain, char* message) { } else if (bar_item->type == BAR_COMPONENT_GROUP) { struct token member = position; + + int index = bar_manager_get_item_index_for_name(&g_bar_manager, + member.text ); + + if (index > 0 + && g_bar_manager.bar_items[index]->position == POSITION_POPUP) { + + popup_add_item(&g_bar_manager.bar_items[index]->parent->popup, + bar_item ); + bar_item->position = POSITION_POPUP; + } + if (index >= 0) + group_add_member(bar_item->group, g_bar_manager.bar_items[index]); + else { + respond(rsp, "[?] Add (Group) %s: Failed to add member '%s', item not found\n", bar_item->name, member.text); + } + member = get_token(&message); while (member.text && member.length > 0) { int index = bar_manager_get_item_index_for_name(&g_bar_manager, diff --git a/src/popup.c b/src/popup.c index 1d1f8ca..8807589 100644 --- a/src/popup.c +++ b/src/popup.c @@ -2,11 +2,12 @@ #include "bar_item.h" #include "bar_manager.h" -void popup_init(struct popup* popup) { +void popup_init(struct popup* popup, struct bar_item* host) { popup->drawing = false; popup->horizontal = false; popup->mouse_over = false; popup->overrides_cell_size = false; + popup->needs_ordering = false; popup->anchor = (CGPoint){0, 0}; popup->y_offset = 0; popup->adid = 0; @@ -15,6 +16,7 @@ void popup_init(struct popup* popup) { popup->num_items = 0; popup->cell_size = 30; popup->items = NULL; + popup->host = host; background_init(&popup->background); popup->background.border_color = rgba_color_from_hex(0xffff0000); popup->background.color = rgba_color_from_hex(0x44000000); @@ -26,6 +28,46 @@ CGRect popup_get_frame(struct popup* popup) { popup->background.bounds.size.height}}; } +void popup_order_windows(struct popup* popup, int mode) { + window_set_level(&popup->window, kCGScreenSaverWindowLevel); + SLSOrderWindow(g_connection, popup->window.id, 1, 0); + + struct window* previous_window = NULL; + for (int i = 0; i < popup->num_items; i++) { + struct bar_item* bar_item = popup->items[i]; + + struct window* window = bar_item_get_window(bar_item, popup->adid); + SLSRemoveFromOrderingGroup(g_connection, window->id); + + window_set_level(window, kCGScreenSaverWindowLevel); + + if (bar_item->type == BAR_COMPONENT_GROUP) { + SLSOrderWindow(g_connection, window->id, mode, popup->window.id); + SLSAddWindowToWindowOrderingGroup(g_connection, + popup->window.id, + window->id, + 1 ); + continue; + } + + if (previous_window) { + SLSOrderWindow(g_connection, window->id, mode, previous_window->id); + SLSAddWindowToWindowOrderingGroup(g_connection, + previous_window->id, + window->id, + 1 ); + } + else { + SLSOrderWindow(g_connection, window->id, mode, popup->window.id); + SLSAddWindowToWindowOrderingGroup(g_connection, + popup->window.id, + window->id, + 1 ); + } + previous_window = window; + } +} + void popup_calculate_bounds(struct popup* popup) { uint32_t y = popup->background.border_width; uint32_t x = 0; @@ -43,6 +85,7 @@ void popup_calculate_bounds(struct popup* popup) { for (int j = 0; j < popup->num_items; j++) { struct bar_item* bar_item = popup->items[j]; if (!bar_item->drawing) continue; + if (bar_item->type == BAR_COMPONENT_GROUP) continue; uint32_t cell_height = max(bar_item_get_height(bar_item), popup->cell_size ); @@ -64,24 +107,48 @@ void popup_calculate_bounds(struct popup* popup) { for (int j = 0; j < popup->num_items; j++) { struct bar_item* bar_item = NULL; - if (popup->horizontal) bar_item = popup->items[j]; - else bar_item = popup->items[popup->num_items - 1 - j]; + bar_item = popup->items[j]; if (!bar_item->drawing) continue; + if (bar_item->type == BAR_COMPONENT_GROUP) continue; uint32_t cell_height = max(bar_item_get_height(bar_item), popup->cell_size ); uint32_t item_x = max((int)x + bar_item->background.padding_left, 0); - uint32_t item_y = y + (popup->horizontal ? height : cell_height) / 2; uint32_t item_height = popup->horizontal ? height : cell_height; + uint32_t item_y = item_height / 2; uint32_t item_width = bar_item->background.padding_right + bar_item->background.padding_left + bar_item_calculate_bounds(bar_item, item_height, - item_x, + 0, item_y ); + uint32_t bar_item_display_length = bar_item_get_length(bar_item, true); + if (popup->adid > 0) { + CGRect frame = {{popup->anchor.x + item_x, + popup->anchor.y + y}, + {bar_item_display_length, + item_height } }; + + window_set_frame(bar_item_get_window(bar_item, popup->adid), frame); + + if (bar_item->group + && group_is_first_member(bar_item->group, bar_item)) { + + uint32_t group_length = group_get_length(bar_item->group); + CGRect group_frame = {{frame.origin.x, + frame.origin.y }, + {group_length, + frame.size.height} }; + + window_set_frame(bar_item_get_window(bar_item->group->members[0], + popup->adid ), + group_frame ); + } + } + if (item_width > width && !popup->horizontal) width = item_width; if (popup->horizontal) x += item_width; else y += cell_height; @@ -102,19 +169,24 @@ void popup_calculate_bounds(struct popup* popup) { popup->background.bounds.size.height = y; popup->background.image.bounds.origin.x = popup->background.border_width; popup->background.image.bounds.origin.y = popup->background.border_width; + + if (popup->adid > 0) + window_set_frame(&popup->window, popup_get_frame(popup)); } void popup_create_window(struct popup* popup) { - window_create(&popup->window, (CGRect){{popup->anchor.x, popup->anchor.y}, - {popup->background.bounds.size.width, - popup->background.bounds.size.height}}); + window_create(&popup->window,(CGRect){{popup->anchor.x, popup->anchor.y}, + {popup->background.bounds.size.width, + popup->background.bounds.size.height}}); if (!popup->background.shadow.enabled) window_disable_shadow(&popup->window); - window_set_level(&popup->window, kCGScreenSaverWindowLevelKey); - CGContextSetInterpolationQuality(popup->window.context, kCGInterpolationNone); - context_set_font_smoothing(popup->window.context, g_bar_manager.font_smoothing); + CGContextSetInterpolationQuality(popup->window.context, + kCGInterpolationNone); + + context_set_font_smoothing(popup->window.context, + g_bar_manager.font_smoothing); popup->drawing = true; } @@ -129,6 +201,7 @@ void popup_add_item(struct popup* popup, struct bar_item* bar_item) { popup->items = realloc(popup->items, sizeof(struct bar_item*)*popup->num_items); popup->items[popup->num_items - 1] = bar_item; + bar_item->parent = popup->host; } bool popup_contains_item(struct popup* popup, struct bar_item* bar_item) { @@ -161,61 +234,45 @@ void popup_remove_item(struct popup* popup, struct bar_item* bar_item) { } void popup_set_anchor(struct popup* popup, CGPoint anchor, uint32_t adid) { - if (popup->anchor.x != anchor.x - || popup->anchor.y != anchor.y + popup->y_offset) { - popup->anchor = anchor; - popup->anchor.y += popup->y_offset; - SLSMoveWindow(g_connection, popup->window.id, &popup->anchor); + popup->anchor = anchor; + popup->anchor.y += popup->y_offset; + + if (adid > 0 && (popup->adid != adid)) { + popup->needs_ordering = true; } + popup->adid = adid; } -void popup_set_drawing(struct popup* popup, bool drawing) { +bool popup_set_drawing(struct popup* popup, bool drawing) { + if (popup->drawing == drawing) return false; if (!drawing && popup->drawing) popup_close_window(popup); else if (drawing && !popup->drawing) popup_create_window(popup); + popup->adid = 0; + return true; } void popup_draw(struct popup* popup) { if (!popup->drawing || popup->adid <= 0) return; - SLSOrderWindow(g_connection, popup->window.id, -1, 0); - window_set_frame(&popup->window, popup_get_frame(popup)); + if (popup->needs_ordering) { + popup_order_windows(popup, 1); + popup->needs_ordering = false; + } + window_apply_frame(&popup->window); - SLSRemoveAllTrackingAreas(g_connection, popup->window.id); - SLSAddTrackingRect(g_connection, popup->window.id, popup->window.frame); CGContextClearRect(popup->window.context, popup->background.bounds); + SLSRemoveAllTrackingAreas(g_connection, popup->window.id); + SLSAddTrackingRect(g_connection, popup->window.id, popup->window.frame); + bool shadow = popup->background.shadow.enabled; popup->background.shadow.enabled = false; background_draw(&popup->background, popup->window.context); popup->background.shadow.enabled = shadow; - for (int i = 0; i < popup->num_items; i++) { - struct bar_item* bar_item = popup->items[i]; - if (!bar_item->drawing) continue; - if (bar_item->update_mask & UPDATE_MOUSE_ENTERED - || bar_item->update_mask & UPDATE_MOUSE_EXITED) { - CGRect tracking_rect = cgrect_mirror_y(bar_item_construct_bounding_rect(bar_item), - popup->background.bounds.size.height / 2. ); - - tracking_rect.origin.y -= tracking_rect.size.height; - // TODO: Fix tracking rects in popups - // SLSAddTrackingRect(g_connection, popup->window.id, tracking_rect); - } - - bar_item_set_bounding_rect_for_display(bar_item, - popup->adid, - popup->anchor, - popup->background.bounds.size.height); - - bool state = bar_item->popup.drawing; - bar_item->popup.drawing = false; - bar_item_draw(bar_item, popup->window.context); - bar_item->popup.drawing = state; - } CGContextFlush(popup->window.context); - SLSOrderWindow(g_connection, popup->window.id, 1, popup->window.id); } void popup_destroy(struct popup* popup) { @@ -231,10 +288,9 @@ bool popup_parse_sub_domain(struct popup* popup, FILE* rsp, struct token propert popup->y_offset = token_to_int(get_token(&message)); return true; } else if (token_equals(property, PROPERTY_DRAWING)) { - popup_set_drawing(popup, - evaluate_boolean_state(get_token(&message), - popup->drawing) ); - return true; + return popup_set_drawing(popup, + evaluate_boolean_state(get_token(&message), + popup->drawing) ); } else if (token_equals(property, PROPERTY_HORIZONTAL)) { popup->horizontal = evaluate_boolean_state(get_token(&message), popup->horizontal ); diff --git a/src/popup.h b/src/popup.h index 4614017..1ed18d5 100644 --- a/src/popup.h +++ b/src/popup.h @@ -10,6 +10,7 @@ struct popup { bool horizontal; bool overrides_cell_size; bool mouse_over; + bool needs_ordering; char align; @@ -20,17 +21,17 @@ struct popup { CGPoint anchor; struct window window; - + struct bar_item* host; struct bar_item** items; uint32_t num_items; struct background background; }; -void popup_init(struct popup* popup); +void popup_init(struct popup* popup, struct bar_item* host); void popup_set_anchor(struct popup* popup, CGPoint anchor, uint32_t adid); void popup_add_item(struct popup* popup, struct bar_item* item); -void popup_set_drawing(struct popup* popup, bool drawing); +bool popup_set_drawing(struct popup* popup, bool drawing); void popup_remove_item(struct popup* popup, struct bar_item* bar_item); uint32_t popup_get_width(struct popup* popup); diff --git a/src/window.c b/src/window.c index 18ebabf..379e5b7 100644 --- a/src/window.c +++ b/src/window.c @@ -56,12 +56,16 @@ void windows_unfreeze() { } void window_set_frame(struct window* window, CGRect frame) { - if (!CGPointEqualToPoint(window->origin, frame.origin)) { + if (window->needs_move + || !CGPointEqualToPoint(window->origin, frame.origin)) { + window->needs_move = true; window->origin = frame.origin; } - if (!CGSizeEqualToSize(window->frame.size, frame.size)) { + if (window->needs_resize + || !CGSizeEqualToSize(window->frame.size, frame.size)) { + window->needs_resize = true; window->frame.size = frame.size; } @@ -76,8 +80,6 @@ bool window_apply_frame(struct window* window) { window->origin.y, frame_region ); - SLSRemoveAllTrackingAreas(g_connection, window->id); - CFRelease(frame_region); window->needs_move = false; window->needs_resize = false;