// prints or dumps the layout of an given tag // first argument tells whether to print or to dump int print_layout_command(int argc, char** argv, GString* output) { HSTag* tag = NULL; // an empty argv[1] means current focused tag if (argc >= 2 && argv[1][0] != '\0') { tag = find_tag(argv[1]); if (!tag) { g_string_append_printf(output, "%s: Tag \"%s\" not found\n", argv[0], argv[1]); return HERBST_INVALID_ARGUMENT; } } else { // use current tag HSMonitor* m = get_current_monitor(); tag = m->tag; } assert(tag != NULL); HSFrame* frame = lookup_frame(tag->frame, argc >= 3 ? argv[2] : ""); if (argc > 0 && !strcmp(argv[0], "dump")) { dump_frame_tree(frame, output); } else { print_frame_tree(frame, output); } return 0; }
int parse_frame_entry(struct frame *pa) { int a, c, i, j, x, y, z; char *token, *running; struct frame *pb = 0; struct object *po = 0; double da, dx, dy; double dgx, dgy, dgz; int frame_nr; char *cptr, *tptr; int screen_lines; int line_height; char font_dir[4096]; char font_name[4096]; font_desc_t *pfd; int temp_palette[16][3]; int text_start, max_width, line_len; struct object *pf = 0; struct object *pc; int bg_height, bg_width; if(debug_flag) { tc_log_msg(MOD_NAME, "subtitler(): parse_frame_entry():\n\ pa->name=%s pa->type=%d\n\ pa->end_frame=%d\n\ pa->data=%lu", pa -> name, pa -> type, pa -> end_frame, (unsigned long)pa -> data); } if(pa -> data[0] == '*') { /* parse the data line */ running = strsave(pa -> data); if(! running) { tc_log_warn(MOD_NAME, "subtitler(): strsave(pa -> data) failed"); return -1; } po = 0; while(1) { token = strsep (&running, " "); if(token == NULL) break; if(debug_flag) { tc_log_msg(MOD_NAME, "token=%s", token); } /* avoid empty string */ if(token[0] == 0) continue; /* check for object reference */ if(token[0] == '*') { /* recursive we are in our own list */ pb = lookup_frame(token); if(! pb) { tc_log_msg(MOD_NAME, "subtitler(): undefined object referenced: %s ignoring", token); return 1; // exit(1); } /* get data for this object */ if(debug_flag) { // tc_log_msg(MOD_NAME, "parser(): object %s data=%s", token, pb -> data); } /* add this object to the display list, if it is already there, we get a pointer to it. */ po = install_object_at_end_of_list(token); if(! po) { tc_log_msg(MOD_NAME, "subtitler(): parse_frame_entry():\n\ could not install or find object %s in display list",\ token); exit(1); } } else /* token[0] != 0, must be an argument */ { /* modify arguments for display object */ /* po must have been set in the preceeding argument in this line, so '11 *this vpos=5', but '11 vops=5 *this' will NOT work, and cause an error exit. */ if(! po) { tc_log_msg(MOD_NAME, "subtitler(): syntax error (object must be first), line reads:\n\ %s", pa -> name); exit(1); } /* copy data if not there yet */ if(! po -> data) { po -> type = pb -> type; po -> data = pb -> data; po -> org_xsize = (double) pb -> xsize; po -> org_ysize = (double) pb -> ysize; po -> org_zsize = (double) pb -> zsize; po -> xsize = (double) pb -> xsize; po -> ysize = (double) pb -> ysize; po -> zsize = (double) pb -> zsize; po -> id = pb -> id; po -> pfd = pb -> pfd; pa -> status = OBJECT_STATUS_NEW; /* set some defaults */ po -> extra_character_space = extra_character_space; } /* parse line */ sscanf(token, "de_stripe=%lf", &po -> de_stripe); sscanf(token, "show_output=%lf", &po -> show_output); sscanf(token, "xpos=%lf", &po -> xpos); sscanf(token, "ypos=%lf", &po -> ypos); sscanf(token, "zpos=%lf", &po -> zpos); sscanf(token, "dxpos=%lf", &po -> dxpos); sscanf(token, "dypos=%lf", &po -> dypos); sscanf(token, "dzpos=%lf", &po -> dzpos); a = sscanf(token, "xdest=%lf", &dgx); if(a) po -> status |= OBJECT_STATUS_HAVE_X_DEST; a = sscanf(token, "ydest=%lf", &dgy); if(a) po -> status |= OBJECT_STATUS_HAVE_Y_DEST; a = sscanf(token, "zdest=%lf", &dgz); if(a) po -> status |= OBJECT_STATUS_HAVE_Z_DEST; if(\ (po -> status & OBJECT_STATUS_HAVE_X_DEST) ||\ (po -> status & OBJECT_STATUS_HAVE_Y_DEST) ||\ (po -> status & OBJECT_STATUS_HAVE_Z_DEST)\ ) { /* use current position if nothing specified */ if(po -> status & OBJECT_STATUS_HAVE_X_DEST) { po -> xdest = dgx; } else { po -> xdest = po -> xpos; } if(po -> status & OBJECT_STATUS_HAVE_Y_DEST) { po -> ydest = dgy; } else { po -> ydest = po -> ypos; } if(! po -> status & OBJECT_STATUS_HAVE_Z_DEST) { po -> zdest = dgz; } else { po -> zdest = po -> zpos; } /* calculate a distance */ /* x distance */ dx = po -> xdest - po -> xpos; /* since the 'heading' calculation in object_list.c uses aspect correction, we have to to pre-correct here the other way around. */ dx *=\ (double)image_height / (double)image_width; /* y distance */ dy = po -> ydest - po -> ypos; /* true distance */ po -> distance = sqrt( (dx * dx) + (dy * dy) ); /* sine */ da = dx / po -> distance; /* calculate a heading angle */ errno = 0; po -> heading = asin(da); if(errno == EDOM) { tc_log_perror(MOD_NAME, "subtitler(): parse_frame_entry():\n\ asin NOT A NUMBER :-)"); exit(1); } /* flip y, x=0, y=0 is top left */ dy = -1 * dy; /* if dy is negative, we move to the other 2 quadrants */ if(dy < 0) po -> heading = M_PI - po -> heading; po -> heading *= 180.0 / M_PI; /* indicate we are on our way */ po -> status |= OBJECT_STATUS_GOTO; /* in object list we will now each frame substract the travelled distance, until po -> distance is 0. Then we will reset the mode to NEW. */ } /* end if some x, y, or z dest */ sscanf(token, "xrot=%lf", &po -> xrotation); sscanf(token, "yrot=%lf", &po -> yrotation); sscanf(token, "zrot=%lf", &po -> zrotation); sscanf(token, "dxrot=%lf", &po -> dxrotation); sscanf(token, "dyrot=%lf", &po -> dyrotation); sscanf(token, "dzrot=%lf", &po -> dzrotation); sscanf(token, "xshear=%lf", &po -> xshear); sscanf(token, "yshear=%lf", &po -> yshear); sscanf(token, "zshear=%lf", &po -> zshear); sscanf(token, "dxshear=%lf", &po -> dxshear); sscanf(token, "dyshear=%lf", &po -> dyshear); sscanf(token, "dzshear=%lf", &po -> dzshear); sscanf(token, "xsize=%lf", &po -> xsize); sscanf(token, "ysize=%lf", &po -> ysize); sscanf(token, "zsize=%lf", &po -> zsize); sscanf(token, "dxsize=%lf", &po -> dxsize); sscanf(token, "dysize=%lf", &po -> dysize); sscanf(token, "dzsize=%lf", &po -> dzsize); if(strncmp(token, "rsize", 5) == 0) { po -> xsize = po -> org_xsize; po -> ysize = po -> org_ysize; po -> zsize = po -> org_zsize; po -> dxsize = 0.0; po -> dysize = 0.0; po -> dzsize = 0.0; } sscanf(token, "heading=%lf", &po -> heading); sscanf(token, "dheading=%lf", &po -> dheading); sscanf(token, "speed=%lf", &po -> speed); sscanf(token, "dspeed=%lf", &po -> dspeed); sscanf(token, "ddspeed=%lf", &po -> ddspeed); sscanf(token, "transp=%lf", &po -> transparency); sscanf(token, "dtransp=%lf", &po -> dtransparency); sscanf(token, "sat=%lf", &po -> saturation); sscanf(token, "dsat=%lf", &po -> dsaturation); sscanf(token, "hue=%lf", &po -> hue); sscanf(token, "dhue=%lf", &po -> dhue); sscanf(token, "hue_ldrift=%lf", &po -> hue_line_drift); sscanf(token, "dhue_ldrift=%lf", &po -> dhue_line_drift); sscanf(token, "contr=%lf", &po -> contrast); sscanf(token, "dcontr=%lf", &po -> dcontrast); sscanf(token, "u_shift=%lf", &po -> u_shift); sscanf(token, "du_shift=%lf", &po -> du_shift); sscanf(token, "v_shift=%lf", &po -> v_shift); sscanf(token, "dv_shift=%lf", &po -> dv_shift); sscanf(token, "slice=%lf", &po -> slice_level); sscanf(token, "dslice=%lf", &po -> dslice_level); sscanf(token, "mask=%lf", &po -> mask_level); sscanf(token, "dmask=%lf", &po -> dmask_level); sscanf(token, "bright=%lf", &po -> brightness); sscanf(token, "dbright=%lf", &po -> dbrightness); sscanf(token, "ck_color=%lf", &po -> chroma_key_color); sscanf(token, "dck_color=%lf", &po -> dchroma_key_color); sscanf(token, "ck_sat=%lf", &po -> chroma_key_saturation); sscanf(token, "dck_sat=%lf", &po -> dchroma_key_saturation); sscanf(token, "ck_window=%lf", &po -> chroma_key_window); sscanf(token, "dck_window=%lf", &po -> dchroma_key_window); sscanf(token, "u=%lf", &po -> u); sscanf(token, "du=%lf", &po -> du); sscanf(token, "v=%lf", &po -> v); sscanf(token, "dv=%lf", &po -> dv); sscanf(token, "color=%lf", &po -> color); sscanf(token, "dcolor=%lf", &po -> dcolor); a = sscanf(token, "center=%lf", &da); if(a == 1) center_flag = (int)da; sscanf(token, "aspect=%lf", &po -> aspect); /* these are globals (double) for subtitles */ sscanf(token, "hfactor=%lf", &subtitle_h_factor); sscanf(token, "vfactor=%lf", &subtitle_v_factor); /* font related */ font_dir[0] = 0; a = sscanf(token, "font_dir=%s", font_dir); if(a == 1) { po -> font_dir = strsave(font_dir); if(! po -> font_dir) { tc_log_msg(MOD_NAME, "subtitler: parse_frame_entry(): could not allocate space for font_dir, aborting"); exit(1); } } /* also allow font_path, for compatibility with xste-3.1 */ a = sscanf(token, "font_path=%s", font_dir); if(a == 1) { po -> font_dir = strsave(font_dir); if(! po -> font_dir) { tc_log_msg(MOD_NAME, "subtitler: parse_frame_entry(): could not allocate space for font_dir, aborting"); exit(1); } } font_name[0] = 0; a = sscanf(token, "font_name=%s", font_name); if(a == 1) { po -> font_name = strsave(font_name); if(! po -> font_name) { tc_log_msg(MOD_NAME, "subtitler: parse_frame_entry(): could not allocate space for font_name, aborting"); exit(1); } } a = sscanf(token, "font_size=%d", &po -> font_size); a = sscanf(token, "font_iso_extension=%d", &po -> font_iso_extension); a = sscanf(token, "font_outline_thickness=%lf", &po -> font_outline_thickness); a = sscanf(token, "font_blur_radius=%lf", &po -> font_blur_radius); if(debug_flag) { tc_log_msg(MOD_NAME, "frame=%s font_dir=%s font_name=%s\n\ font_size=%d font_iso_extension=%d font_outline_thickness=%.2f font_blur_radius=%.2f",\ pa -> name, po -> font_dir, po -> font_name,\ po -> font_size, po -> font_iso_extension,\ po -> font_outline_thickness, po -> font_blur_radius); } /* also reload font if font_factor changed */ if( (po -> font_dir) && (po -> font_name) &&\ (po -> font_size > 0) && (po -> font_iso_extension > 0) &&\ (po -> font_outline_thickness > 0.0) && (po -> font_blur_radius > 0.0) ) { /* IMPORTANT! this sets data in frame_list (pb)!!!!! NOT<< in object_list (po). In fact replaces frame_list pb -> font_dir with the new definition. Later, when the object is referenced again, a pointer is handed to the object list. Else the data would be erased when the object was no longer displayed. */ po -> font_symbols = default_subtitle_font_symbols; /* read in font (also needed for frame counter) */ pfd = add_font(\ po -> font_name, po -> font_symbols, po -> font_size, po -> font_iso_extension,\ po -> font_outline_thickness, po -> font_blur_radius); if(! pfd) { tc_log_msg(MOD_NAME, "subtitler(): parser.c: could not load font:\n\ font_dir=%s font_name=%s symbols=%d size=%d iso extension=%d\n\ outline_thickness=%.2f blur_radius=%.2f, aborting",\ po -> font_dir, po -> font_name, po -> font_symbols, po -> font_size,\ po -> font_iso_extension,\ po -> font_outline_thickness, po -> font_blur_radius ); /* return error */ exit(1); }
HSClient* manage_client(Window win) { if (is_herbstluft_window(g_display, win)) { // ignore our own window return NULL; } if (get_client_from_window(win)) { return NULL; } // init client HSClient* client = create_client(); client->pid = window_pid(g_display, win); HSMonitor* m = get_current_monitor(); // set to window properties client->window = win; client_update_title(client); unsigned int border, depth; Window root_win; int x, y; unsigned int w, h; XGetGeometry(g_display, win, &root_win, &x, &y, &w, &h, &border, &depth); // treat wanted coordinates as floating coords client->float_size.x = x; client->float_size.y = y; client->float_size.width = w; client->float_size.height = h; // apply rules HSClientChanges changes; client_changes_init(&changes, client); rules_apply(client, &changes); if (changes.tag_name) { client->tag = find_tag(changes.tag_name->str); } if (!changes.manage) { client_changes_free_members(&changes); client_destroy(client); // map it... just to be sure XMapWindow(g_display, win); return NULL; } // actually manage it g_hash_table_insert(g_clients, &(client->window), client); client->window_str = g_string_sized_new(10); g_string_printf(client->window_str, "0x%lx", win); hsobject_link(g_client_object, &client->object, client->window_str->str); // insert to layout if (!client->tag) { client->tag = m->tag; } // get events from window XSelectInput(g_display, win, CLIENT_EVENT_MASK); // insert window to the stack client->slice = slice_create_client(client); stack_insert_slice(client->tag->stack, client->slice); // insert window to the tag frame_insert_window(lookup_frame(client->tag->frame, changes.tree_index->str), win); client_update_wm_hints(client); if (changes.focus) { // give focus to window if wanted // TODO: make this faster! // WARNING: this solution needs O(C + exp(D)) time where W is the count // of clients on this tag and D is the depth of the binary layout tree frame_focus_window(client->tag->frame, win); } HSAttribute attributes[] = { ATTRIBUTE_STRING( "winid", client->window_str, ATTR_READ_ONLY), ATTRIBUTE_STRING( "title", client->title, ATTR_READ_ONLY), ATTRIBUTE_BOOL( "fullscreen", client->fullscreen, client_attr_fullscreen), ATTRIBUTE_BOOL( "pseudotile", client->pseudotile, client_attr_pseudotile), ATTRIBUTE_BOOL( "ewmhrequests", client->ewmhrequests, ATTR_ACCEPT_ALL), ATTRIBUTE_BOOL( "ewmhnotify", client->ewmhnotify, ATTR_ACCEPT_ALL), ATTRIBUTE_BOOL( "sizehints", client->sizehints, ATTR_ACCEPT_ALL), ATTRIBUTE_BOOL( "urgent", client->urgent, client_attr_urgent), ATTRIBUTE_LAST, }; hsobject_set_attributes(&client->object, attributes); ewmh_window_update_tag(client->window, client->tag); tag_set_flags_dirty(); client_set_fullscreen(client, changes.fullscreen); ewmh_update_window_state(client); // add client after setting the correct tag for the new client // this ensures a panel can read the tag property correctly at this point ewmh_add_client(client->window); HSMonitor* monitor = find_monitor_with_tag(client->tag); if (monitor) { if (monitor != get_current_monitor() && changes.focus && changes.switchtag) { monitor_set_tag(get_current_monitor(), client->tag); } // TODO: monitor_apply_layout() maybe is called twice here if it // already is called by monitor_set_tag() monitor_apply_layout(monitor); } else { if (changes.focus && changes.switchtag) { monitor_set_tag(get_current_monitor(), client->tag); } } client_changes_free_members(&changes); grab_client_buttons(client, false); return client; }