📄 tool_bdry.c
字号:
#ifndef lint#ifdef sccsstatic char sccsid[] = "@(#)tool_bdry.c 1.1 92/07/30 Copyr 1984 Sun Micro";#endif#endif/* * Copyright (c) 1983 by Sun Microsystems, Inc. *//* * Does tool interactive boundary mgt. */#include <sys/types.h>#include <sys/file.h>#include <sys/time.h>#include <sys/wait.h>#include <errno.h>#include <signal.h>#include <sundev/kbd.h>#include <pixrect/pixrect.h>#include <pixrect/pixfont.h>#include <sunwindow/rect.h>#include <sunwindow/rectlist.h>#include <sunwindow/pixwin.h>#include <sunwindow/cms_mono.h>#include <sunwindow/win_struct.h>#include <sunwindow/win_cursor.h>#include <sunwindow/win_input.h>#include <suntool/wmgr.h>#include <suntool/icon.h>#include <suntool/tool.h>#define MIN_SW_WIDTH 16#define MIN_SW_HEIGHT 16typedef enum border_side { BORDERS_NONE, BORDERS_LEFT, BORDERS_RIGHT, BORDERS_TOP, BORDERS_BOTTOM} Border;static Border rect_border();static Toolsw *nearest_sw(), *resolve_xy_to_sw();static adjust_position();extern void tool_expand_neighbors(), tool_compute_constraint();static void constrain_sw(), compute_obstacles(), compute_shadows(), constrain_from_tool(), constrain_neighbor(), change_sw(), sw_set_rect(), get_tool_info(), compute_contortion();inttool_moveboundary(tool, event) register Tool *tool; register Event *event;{ Toolsw *target_sw; register int x = event_x(event), y = event_y(event); int is_move = !event_ctrl_is_down(event); int wants_fill = !event_shift_is_down(event); int swsp = tool_subwindowspacing(tool); int top_border = tool_stripeheight(tool) + 2; Rect old_rect, new_rect; Rect rconstrain; WM_Direction grasp; Rectlist obstacles; int x_used, y_used; extern WM_Direction wmgr_compute_grasp(); if (~tool->tl_flags&TOOL_BOUNDARYMGR || (tool->tl_rectcache.r_width - swsp <= x) || (tool->tl_rectcache.r_height - swsp <= y) || (tool->tl_rectcache.r_left + swsp >= x) || (tool->tl_rectcache.r_top + top_border >= y)) return(-1); target_sw = nearest_sw(tool, x, y, (int *)LINT_CAST(&x_used), (int *)LINT_CAST(&y_used)); if (!target_sw) return (-1); event_set_x(event, x_used); event_set_y(event, y_used); /* * Determine constrainning rect */ (void)win_getrect(target_sw->ts_windowfd, &old_rect); new_rect = old_rect; grasp = wmgr_compute_grasp(&new_rect, event, is_move, FALSE, TRUE); constrain_sw(tool, target_sw, grasp, is_move, &rconstrain); /* Compute the obstacles posed * by the other subwindows */ compute_obstacles(tool, target_sw, &obstacles); /* * Display feedback that the user drags around the screen. */ wmgr_providefeedback(tool->tl_windowfd, &new_rect, event, is_move, FALSE, grasp, &rconstrain, (int (*)())adjust_position, (int)(swsp / 2), &obstacles); (void)rl_free(&obstacles); /* Nothing to do if rect * size/position did not change. */ if (rect_equal(&new_rect, &old_rect)) return(0); /* Apply the new subwindow position/size */ change_sw(tool, target_sw, &new_rect, wants_fill); /* expand the subwindow's former neighbors * to fill any new holes. */ if (wants_fill) tool_expand_neighbors(tool, target_sw, &old_rect); /* call the client's subwindow layout routine * so the client knows the subwindows have changed. * Note that the default routine will not alter the * subwindows, since the above code will have adjusted * the subwindows already. */ (void)tool_layoutsubwindows(tool); /* * Need to redisplay the tool because the sw boundaries need to be * fixed up. */ (void)_tool_display(tool, FALSE); return(0);}static Toolsw *nearest_sw(tool, x, y, x_used, y_used) Tool *tool; register int x, y; register int *x_used, *y_used;{ register Toolsw *result = resolve_xy_to_sw(tool, x, y); register Toolsw *sw; int min_dist_sq = 0x7FFFFFFF; register int dist_sq; int x_int, y_int; Rect rect; /* might be in a subwindow. * In that case return 0. */ if (result) { (void)win_getrect(result->ts_windowfd, &rect); if (rect_includespoint(&rect, x, y)) return (Toolsw *) 0; if (x_used) *x_used = x; if (y_used) *y_used = y; return result; } /* not in a subwindow or on any border. * look for the closest subwindow. */ for (sw = tool->tl_sw; sw; sw = sw->ts_next) { (void)win_getrect(sw->ts_windowfd, &rect); dist_sq = rect_distance(&rect, x, y, &x_int, &y_int); if (dist_sq < min_dist_sq) { min_dist_sq = dist_sq; result = sw; if (x_used) *x_used = x_int; if (y_used) *y_used = y_int; } } return(result);}static Toolsw *resolve_xy_to_sw(tool, x, y) register Tool *tool; register int x, y;{ register Toolsw *sw; Rect rect, rtest; Toolsw *target_sw = 0; int swsp = tool_subwindowspacing(tool); /* * Find sw window which is above or to left of position */ for (sw = tool->tl_sw; sw; sw = sw->ts_next) { (void)win_getrect(sw->ts_windowfd, &rect); if (rect_includespoint(&rect, x, y)) return sw; /* First check the bottom edge */ rect_construct(&rtest, rect.r_left, rect_bottom(&rect), rect.r_width, swsp+1); if (rect_includespoint(&rtest, x, y)) return sw; /* Now check the right edge */ rect_construct(&rtest, rect_right(&rect), rect.r_top, swsp, rect.r_height+1); if (rect_includespoint(&rtest, x, y)) return sw; /* Now check the top edge */ rect_construct(&rtest, rect.r_left, rect.r_top - swsp, rect.r_width, swsp+1); if (rect_includespoint(&rtest, x, y)) { target_sw = sw; continue; } /* Now check the left edge */ rect_construct(&rtest, rect.r_left - swsp, rect.r_top, swsp, rect.r_height+1); if (rect_includespoint(&rtest, x, y)) { target_sw = sw; continue; } } return target_sw;}/* Constrain target_sw from moving or stretching * outside the tool. */static void constrain_sw(tool, target_sw, grasp, is_move, rconstrain)Tool *tool;Toolsw *target_sw;WM_Direction grasp;int is_move;Rect *rconstrain;{ Rect target_rect; extern Rect wmgr_set_bounds(); constrain_from_tool(tool, rconstrain); (void)win_getrect(target_sw->ts_windowfd, &target_rect); *rconstrain = wmgr_set_bounds(&target_rect, rconstrain,grasp, is_move, (struct pr_pos *)0, MIN_SW_WIDTH, MIN_SW_HEIGHT); }/* Compute the constraining rect imposed * by the tool. */static void constrain_from_tool(tool, rconstrain)Tool *tool;register Rect *rconstrain;{ short border_width = tool_borderwidth(tool); *rconstrain = tool->tl_rectcache; rconstrain->r_left += border_width; rconstrain->r_width -= 2 * border_width; rconstrain->r_top += tool_stripeheight(tool) + 2; rconstrain->r_height -= tool_stripeheight(tool) + 2 + border_width;} /* Compute the obstacle rectangles posed by the * other subwindows in tool. */static voidcompute_obstacles(tool, target_sw, obstacles)Tool *tool;Toolsw *target_sw;Rectlist *obstacles;{ register Toolsw *sw; register short swsp = tool_subwindowspacing(tool) / 2; Rect rect; *obstacles = rl_null; for (sw = tool->tl_sw; sw; sw = sw->ts_next) { if (sw == target_sw) continue; (void)win_getrect(sw->ts_windowfd, &rect); rect_marginadjust(&rect, swsp); (void)rl_rectunion(&rect, obstacles, obstacles); }}/* If new_rect collides with an obstacle and the obstacle can't * be contorted, use old_rect instead. This is called by * wmgr_providefeedback() in wmgr_rect.c. */staticadjust_position(obstacles, swsp, old_rect, new_rect)Rectlist *obstacles;short swsp;Rect *old_rect, *new_rect;{ register Rectnode *rnode; register Rect *r; short width_left, width_right, width; short height_above, height_below, height; rect_marginadjust(new_rect, swsp + 1); for (rnode = obstacles->rl_head; rnode; rnode = rnode->rn_next) { r = &rnode->rn_rect; if (rect_intersectsrect(r, new_rect)) { compute_contortion(r, new_rect, &width_left, &width_right, &width, &height_above, &height_below, &height); if ((width < MIN_SW_WIDTH) && (height < MIN_SW_HEIGHT)) { *new_rect = *old_rect; return; } } } rect_marginadjust(new_rect, -(swsp + 1));} /* Expand neighboring subwindows to fill in the * gap caused by changing target_sw from old_rect. */ extern voidtool_expand_neighbors(tool, target_sw, old_rect)Tool *tool;Toolsw *target_sw;Rect *old_rect;{ register Toolsw *sw; Rect rect, rconstrain; register Rect *r = ▭ register short swsp = tool_subwindowspacing(tool) / 2; register Border borders_on; register int hole; int tool_left, tool_top, tool_right, tool_bottom; rect_marginadjust(old_rect, swsp + 1); (void)win_lockdata(tool->tl_windowfd); get_tool_info(tool, &tool_left, &tool_top, &tool_right, &tool_bottom); /* For each subwindow bordering old_rect */ for (sw = tool->tl_sw; sw; sw = sw->ts_next) { if (sw == target_sw) continue; (void)win_getrect(sw->ts_windowfd, r); rect_marginadjust(r, swsp); borders_on = rect_border(r, old_rect);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -