📄 win_central.c
字号:
{#define REDO_LIMIT 3 register Pixwin_handles *pwh; register struct pixwin *pw = ((struct pixwin *)0); Notify_value return_code = NOTIFY_IGNORED; int resize; int damaged_id; int not_fixed_image; int done_damaged_called = 0; int repaint_all = 0; int redo_count = 0; if ((win->next == PIXWIN_HANDLES_NULL) || (win->flags & WH_OWN_SIGWINCH)) return (NOTIFY_IGNORED);Redo: /* Prevent unsolved flicker repaint situation */ if (redo_count++ >= REDO_LIMIT) { (void)pw_donedamaged(pw); return (return_code); } /* * Must get through entire repair process with damaged_id equalling * its initial value at the first pw_damaged or should redo the * fixup. This is because more damage might have occured between * the start and finish. */ damaged_id = 0; resize = 0; not_fixed_image = 0; /* See what needs to be fixed up */ for (pwh = win->next;pwh; pwh = pwh->next) { pw = pwh->pw; (void)pw_damaged(pw); /* See if first time called pw_damaged */ if (damaged_id == 0) damaged_id = pw->pw_clipdata->pwcd_damagedid; /* * Repair as much as possible from retained image unless * resizing. Always repair if client specified a fixed * sized image. */ if (pwh->flags & PW_RESIZED) resize = 1; if ((pwh->flags & PW_RETAIN) && pw->pw_prretained && ((!(pwh->flags & PW_RESIZED)) || (pwh->flags & PW_FIXED_IMAGE))) { struct rect retain_rect; struct rectlist retain_rl; /* Reduce repaired area by intersecting tiles */ win_reduce_by_regions(win, pwh); /* Copy bits to the screen */ (void)pw_repairretained(pw); /* Reduce damaged area by amount repaired */ rect_construct(&retain_rect, 0, 0, pw->pw_prretained->pr_width, pw->pw_prretained->pr_height); (void)rl_initwithrect(&retain_rect, &retain_rl); (void)pw_reduce_clipping(pw, &retain_rl); (void)rl_free(&retain_rl); return_code = NOTIFY_DONE; } if (!(pwh->flags & PW_FIXED_IMAGE)) not_fixed_image = 1; if (pwh->flags & PW_REPAINT_ALL) repaint_all = 1; pwh->flags &= ~PW_RESIZED; } /* * If not fixed size image and resize then set up clipping to be * the new entire exposed area. Perhaps we could be smarter * to reduce repainting by doing this on a pixwin by pixwin basis. */ if ((resize && not_fixed_image) || repaint_all) { if (pw->pw_clipdata->pwcd_damagedid != damaged_id) goto Redo; (void)pw_donedamaged(pw); done_damaged_called = 1; } /* See if any thing else to repair */ for (pwh = win->next;pwh; pwh = pwh->next) { pw = pwh->pw; /* * Make sure every pixwin uses exposed clipping (a redundant * but harmless call for the pixwin that called pw_donedamaged). */ if (done_damaged_called) (void)pw_exposed(pw);#ifndef PRE_FLAMINGO if (!rl_empty(&pw->pw_clipdata->pwcd_clipping) || win->flags & WH_NOTIFY_ALL) {#else if (!rl_empty(&pw->pw_clipdata->pwcd_clipping)) {#endif /* Clear fixed size image */ if (pwh->flags & PW_FIXED_IMAGE) (void)pw_writebackground(pw, 0, 0, win->rect.r_width, win->rect.r_height, PIX_CLR); /* Notify client to repair the rest */ switch (win_post_id(pwh->client, WIN_REPAINT, NOTIFY_SAFE)) { case NOTIFY_OK: if (return_code == NOTIFY_IGNORED) return_code = NOTIFY_DONE; break; case NOTIFY_NO_CONDITION: /* * Client may actually be handling * SIGWINCHes himself */ break; default: notify_perror("pw_change"); return_code = NOTIFY_UNEXPECTED; } } /* * If haven't yet, set pixwin to exposed. Last pixwin handled * below. */ if (!done_damaged_called && pwh->next != PIXWIN_HANDLES_NULL) (void)pw_exposed(pw); } /* Tell kernel that fixed up image and reset clipping to exposed */ if (!done_damaged_called) { if (pw->pw_clipdata->pwcd_damagedid != damaged_id) goto Redo; (void)pw_donedamaged(pw); } return (return_code);}/* * Reduce repaired area by intersecting tiles, * if full window pixwin. Can't just reduce by * overlapping tiles because there is no notion * of overlapping tiles. Choose only full window * pixwin because if did it arbitrarily, there * would not be any bits written for the intersection. * (This supports 3.0 textsw's that migrated to be able * to be retained in 3.2). */staticwin_reduce_by_regions(win, pwh_main) Window_handles *win; register Pixwin_handles *pwh_main;{ struct rectlist rl; register Pixwin_handles *pwh_region; if (pwh_main->pw->pw_clipdata->pwcd_regionrect) return; rl = rl_null; for (pwh_region = win->next;pwh_region; pwh_region = pwh_region->next) { if (pwh_region->pw->pw_clipdata->pwcd_regionrect == RECT_NULL) continue; (void)rl_rectunion(pwh_region->pw->pw_clipdata->pwcd_regionrect, &rl, &rl); } (void)pw_reduce_clipping(pwh_main->pw, &rl); (void)rl_free(&rl);}static Notify_valuepw_destroy_handles(client, status) Notify_client client; Destroy_status status;{ if (status != DESTROY_CHECKING) (void)win_unregister(client); return(NOTIFY_DONE);}static Window_handles *win_get_handles(client, pwh_ptr) Notify_client client; register Pixwin_handles **pwh_ptr;{ register int i; register Window_handles *win; Pixwin_handles *pwh; if (wins == WINDOW_HANDLES_NULL) return(WINDOW_HANDLES_NULL); /* Search through windows */ for (i = 0; i < win_num; i++) { win = &wins[i]; /* Search through pixwin clients */ if ((pwh = win_find_handles(client, win)) != PIXWIN_HANDLES_NULL) { if (pwh_ptr) *pwh_ptr = pwh; return(win); } } /* Didn't find client */ if (pwh_ptr) *pwh_ptr = PIXWIN_HANDLES_NULL; return(WINDOW_HANDLES_NULL);}static intwin_remove_handles(win, pwh_axe) register Window_handles *win; register Pixwin_handles *pwh_axe;{ register Pixwin_handles **pwh_ptr; register Pixwin_handles *pwh; /* Search through pixwin clients */ pwh_ptr = &win->next; for (pwh = win->next;pwh; pwh = pwh->next) { if (pwh == pwh_axe) { /* Fix up list pointer */ *pwh_ptr = pwh->next; /* Remove win references to pwh */ if (win->latest == pwh_axe) win->latest = PIXWIN_HANDLES_NULL; if (win->current == pwh_axe) win->current = PIXWIN_HANDLES_NULL; return (0); } pwh_ptr = &pwh->next; } return (-1);}static Pixwin_handles *win_find_handles(client, win) Notify_client client; register Window_handles *win;{ register Pixwin_handles *pwh; /* Search through pixwin clients */ for (pwh = win->next;pwh; pwh = pwh->next) { if (pwh->client == client) return(pwh); } return(PIXWIN_HANDLES_NULL);}static Pixwin_handles *win_find_consumer(win, event) register Window_handles *win; register Event *event;{ register Pixwin_handles *pwh = PIXWIN_HANDLES_NULL; register Pixwin_handles *pwh_default = PIXWIN_HANDLES_NULL; Pixwin_handles *pwh_largest; Rect rect; int biggest_area, test_area; register int enters = 1; /* If input is grabbed then send to the grabber */ if ((win->flags & WH_GRABBED_INPUT) && win->latest) return(win->latest); /* Search through pixwin clients */ for (pwh = win->next;pwh; pwh = pwh->next) { /* Find region that includes x and y */ if (pwh->pw->pw_clipdata->pwcd_regionrect) rect = *pwh->pw->pw_clipdata->pwcd_regionrect; else /* Make rect in own coordinate space */ rect_construct(&rect, 0, 0, win->rect.r_width, win->rect.r_height); if (rect_includespoint(&rect, event->ie_locx, event->ie_locy)) goto Found; if (pwh->flags & PW_INPUT_DEFAULT) pwh_default = pwh; } /* Suppress sending of any enters */ enters = 0; /* * Event doesn't fall within any region's rectangle so assume * send input to the default region. Multiple regions that want * to change the kbd focus would need to explicitly change the * default region. */ if (pwh_default) { pwh = pwh_default; goto Found; } /* * Since there wasn't any default region then guess that * the latest region sent input to is the keyboard focus. */ if (win->latest) { pwh = win->latest; goto Found; } /* * If there is no default or no latest, then the region with the * biggest area is a third guess (assuming subwindow with scrollbars). */ pwh_largest = pwh; biggest_area = 0; for (pwh = win->next;pwh; pwh = pwh->next) { /* Find region that includes x and y */ if (pwh->pw->pw_clipdata->pwcd_regionrect) rect = *pwh->pw->pw_clipdata->pwcd_regionrect; else /* Make rect in own coordinate space */ rect_construct(&rect, 0, 0, win->rect.r_width, win->rect.r_height); test_area = rect.r_width * rect.r_height; if (test_area > biggest_area) { pwh_largest = pwh; biggest_area = test_area; } } pwh = pwh_largest;Found: /* Remember latest pixwin directed input towards */ win->latest = pwh; /* See if exiting window */ if (event->ie_code == LOC_WINEXIT) enters = 0; /* * Send region exit if have entered region and the input recipent * is now different. */ if (win->current && ((win->current != pwh) || (event->ie_code == LOC_WINEXIT))) win_rgnexit(win, event); /* Try sending region enter if last event sent was exit */ if (enters && (win->current == PIXWIN_HANDLES_NULL)) { /* Delay region enter if window enter */ if (event->ie_code == LOC_WINENTER) { pwh->flags |= PW_DELAYED_ENTER; win->current = pwh; } else win_rgnenter(win, event, pwh); } return(pwh);}static Notify_errorwin_send(pwh, event, when, arg, copy_func, release_func) Pixwin_handles *pwh; register Event *event; Notify_event_type when; Notify_arg arg; Notify_copy copy_func; Notify_release release_func;{ register Rect *rect; short x_save = event->ie_locx; short y_save = event->ie_locy; Notify_error error; short pw_delayed_enter = (pwh->flags & PW_DELAYED_ENTER); Notify_client client = pwh->client; /* Translate mouse x and y */ rect = pwh->pw->pw_clipdata->pwcd_regionrect; if (rect && !(pwh->flags & PW_NO_LOC_ADJUST)) { event->ie_locx -= rect->r_left; event->ie_locy -= rect->r_top; } /* Post event */ error = notify_post_event_and_arg(client, (Notify_event)event, when, arg, copy_func, release_func); if (error != NOTIFY_OK) notify_perror("win_send"); /* Restore mouse x and y to base because win_event shared with others */ event->ie_locx = x_save; event->ie_locy = y_save; /* Send delayed enter (don't rely on pwh being around any more) */ if (pw_delayed_enter) { Window_handles *win = win_get_handles(client, &pwh); if (pwh != PIXWIN_HANDLES_NULL) { pwh->flags &= ~PW_DELAYED_ENTER; win_rgnenter(win, event, pwh); } } return (error);}staticwin_rgnenter(win, event, pwh) register Window_handles *win; register Event *event; Pixwin_handles *pwh;{ unsigned short id = event->ie_code; unsigned short action = event_action(event); /* Make input sink */ win->current = pwh; /* Send region enter event */ event_set_id(event, LOC_RGNENTER); (void) win_send(pwh, event, NOTIFY_SAFE, (Notify_arg)0, win_copy_event, win_free_event); event->ie_code = id; /* this madness because event_*_action semantics are screwed */ if (action != id) event_set_action(event, action); return;}staticwin_rgnexit(win, event) register Window_handles *win; register Event *event;{ unsigned short id = event->ie_code; unsigned short action = event_action(event); if (win->current == PIXWIN_HANDLES_NULL) return; /* Send enter event */ event_set_id(event, LOC_RGNEXIT); (void) win_send(win->current, event, NOTIFY_SAFE, (Notify_arg)0, win_copy_event, win_free_event); event->ie_code = id; /* this madness because event_*_action semantics are screwed */ if (action != id) event_set_action(event, action); /* No one currently has locator in it */ win->current = PIXWIN_HANDLES_NULL; return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -