/* Arguments work exactly like for FScreenGetScrRect() */ void FScreenCenterOnScreen( fscreen_scr_arg *arg, fscreen_scr_t screen, int *x, int *y, int w, int h) { int sx; int sy; int sw; int sh; int lx; int ly; FScreenGetScrRect(arg, screen, &sx, &sy, &sw, &sh); lx = (sw - w) / 2; ly = (sh - h) / 2; if (lx < 0) lx = 0; if (ly < 0) ly = 0; lx += sx; ly += sy; if (x) { *x = lx; } if (y) { *y = ly; } return; }
/* Arguments work exactly like for FScreenGetScrRect() */ Bool FScreenIsRectangleOnScreen( fscreen_scr_arg *arg, fscreen_scr_t screen, rectangle *rec) { int sx; int sy; int sw; int sh; FScreenGetScrRect(arg, screen, &sx, &sy, &sw, &sh); return (rec->x + rec->width > sx && rec->x < sx + sw && rec->y + rec->height > sy && rec->y < sy + sh) ? True : False; }
void FScreenGetResistanceRect( int wx, int wy, unsigned int ww, unsigned int wh, int *x0, int *y0, int *x1, int *y1) { fscreen_scr_arg arg; arg.xypos.x = wx + ww / 2; arg.xypos.y = wy + wh / 2; FScreenGetScrRect(&arg, FSCREEN_XYPOS, x0, y0, x1, y1); *x1 += *x0; *y1 += *y0; return; }
/* Translates the coodinates *x *y from the screen specified by arg_src and * screen_src to coordinates on the screen specified by arg_dest and * screen_dest. (see FScreenGetScrRect for more details). */ void FScreenTranslateCoordinates( fscreen_scr_arg *arg_src, fscreen_scr_t screen_src, fscreen_scr_arg *arg_dest, fscreen_scr_t screen_dest, int *x, int *y) { int x_src; int y_src; int x_dest; int y_dest; FScreenGetScrRect(arg_src, screen_src, &x_src, &y_src, NULL, NULL); FScreenGetScrRect(arg_dest, screen_dest, &x_dest, &y_dest, NULL, NULL); if (x) { *x = *x + x_src - x_dest; } if (y) { *y = *y + y_src - y_dest; } return; }
/* Arguments work exactly like for FScreenGetScrRect() */ int FScreenClipToScreen( fscreen_scr_arg *arg, fscreen_scr_t screen, int *x, int *y, int w, int h) { int sx; int sy; int sw; int sh; int lx = (x) ? *x : 0; int ly = (y) ? *y : 0; int x_grav = GRAV_POS; int y_grav = GRAV_POS; FScreenGetScrRect(arg, screen, &sx, &sy, &sw, &sh); if (lx + w > sx + sw) { lx = sx + sw - w; x_grav = GRAV_NEG; } if (ly + h > sy + sh) { ly = sy + sh - h; y_grav = GRAV_NEG; } if (lx < sx) { lx = sx; x_grav = GRAV_POS; } if (ly < sy) { ly = sy; y_grav = GRAV_POS; } if (x) { *x = lx; } if (y) { *y = ly; } return grav_matrix[y_grav][x_grav]; }
int main(int argc, char *argv[]) { char match[128]; char *config_line; int scr; console = fopen("/dev/console","w"); if (!console) console = stderr; module = ParseModuleArgs(argc,argv,0); if (module == NULL) { fprintf(stderr,"FvwmRearrange: module should be executed by fvwm only\n"); exit(-1); } fd[0] = module->to_fvwm; fd[1] = module->from_fvwm; if (!(dpy = XOpenDisplay(NULL))) { fprintf(console, "%s: couldn't open display %s\n", module->name, XDisplayName(NULL)); exit(-1); } signal (SIGPIPE, DeadPipe); FScreenInit(dpy); scr = DefaultScreen(dpy); fd_width = GetFdWidth(); strcpy(match, "*"); strcat(match, module->name); InitGetConfigLine(fd,match); GetConfigLine(fd, &config_line); while (config_line != NULL) { if (strncasecmp(config_line, XINERAMA_CONFIG_STRING, sizeof(XINERAMA_CONFIG_STRING) - 1) == 0) { FScreenConfigureModule( config_line + sizeof(XINERAMA_CONFIG_STRING) - 1); } GetConfigLine(fd, &config_line); } FScreenGetScrRect(NULL, FSCREEN_CURRENT, &dx, &dy, &dwidth, &dheight); if (strcmp(module->name, "FvwmCascade") && (!strcmp(module->name, "FvwmTile") || (argc >= 7 && !strcmp(argv[6], "-tile")))) { FvwmTile = 1; FvwmCascade = 0; resize = 1; } else { FvwmCascade = 1; FvwmTile = 0; resize = 0; } parse_args("module args", module->user_argc, module->user_argv, 0); SetMessageMask(fd, M_CONFIGURE_WINDOW | M_END_WINDOWLIST); SetMessageMask(fd, M_EXTENDED_MSG); if (FvwmTile) { if (maxx == dx) maxx = dx + dwidth; if (maxy == dy) maxy = dy + dheight; } SendText(fd, "Send_WindowList", 0); /* tell fvwm we're running */ SendFinishedStartupNotification(fd); while (get_window()) /* */; if (wins_count) { if (FvwmCascade) cascade_windows(); else /* FvwmTile */ tile_windows(); } free_window_list(wins); if (console != stderr) fclose(console); return 0; }
/* FScreenGetGeometry * Parses the geometry in a form: XGeometry[@screen], i.e. * [=][<width>{xX}<height>][{+-}<xoffset>{+-}<yoffset>][@<screen>] * where <screen> is either a number or "G" (global) "C" (current) * or "P" (primary) * * Args: * parsestring, x_r, y_r, w_r, h_r the same as in XParseGeometry * hints window hints structure, may be NULL * flags bitmask of allowed flags (XValue, WidthValue, XNegative...) * * Note1: * hints->width and hints->height will be used to calc negative geometry * if width/height isn't specified in the geometry itself. * * Note2: * This function's behaviour is crafted to sutisfy/emulate the * FvwmWinList::MakeMeWindow()'s behaviour. * * Note3: * A special value of `flags' when [XY]Value are there but [XY]Negative * aren't, means that in case of negative geometry specification * x_r/y_r values will be promoted to the screen border, but w/h * wouldn't be subtracted, so that the program can do x-=w later * ([XY]Negative *will* be returned, albeit absent in `flags'). * This option is supposed for proggies like FvwmButtons, which * receive geometry specification long before they are able to actually * use it (and which calculate w/h themselves). * (The same effect can't be obtained with omitting {Width,Height}Value * in the flags, since the app may wish to get the dimensions but apply * some constraints later (as FvwmButtons do, BTW...).) * This option can be also useful in cases where dimensions are * specified not in pixels but in some other units (e.g., charcells). */ int FScreenGetGeometry( char *parsestring, int *x_return, int *y_return, int *width_return, int *height_return, XSizeHints *hints, int flags) { int ret; int saved; int x, y; unsigned int w = 0, h = 0; int grav, x_grav, y_grav; int scr = default_geometry_scr; int scr_x, scr_y; int scr_w, scr_h; /* I. Do the parsing and strip off extra bits */ ret = FScreenParseGeometryWithScreen(parsestring, &x, &y, &w, &h, &scr); saved = ret & (XNegative | YNegative); ret &= flags; /* II. Get the screen rectangle */ switch (scr) { case FSCREEN_GLOBAL: case FSCREEN_CURRENT: case FSCREEN_PRIMARY: case FSCREEN_XYPOS: FScreenGetScrRect(NULL, scr, &scr_x, &scr_y, &scr_w, &scr_h); break; default: scr++; if (scr < first_to_check || scr > last_to_check) scr = first_to_check; scr_x = screens[scr].x_org; scr_y = screens[scr].y_org; scr_w = screens[scr].width; scr_h = screens[scr].height; } /* III. Interpret and fill in the values */ /* Fill in dimensions for future negative calculations if * omitted/forbidden */ /* Maybe should use *x_return,*y_return if hints==NULL? * Unreliable... */ if (hints != NULL && hints->flags & PSize) { if ((ret & WidthValue) == 0) { w = hints->width; } if ((ret & HeightValue) == 0) { h = hints->height; } } else { /* This branch is required for case when size *is* specified, * but masked off */ if ((ret & WidthValue) == 0) { w = 0; } if ((ret & HeightValue) == 0) { h = 0; } } /* Advance coords to the screen... */ x += scr_x; y += scr_y; /* ...and process negative geometries */ if (saved & XNegative) { x += scr_w; } if (saved & YNegative) { y += scr_h; } if (ret & XNegative) { x -= w; } if (ret & YNegative) { y -= h; } /* Restore negative bits */ ret |= saved; /* Guess orientation */ x_grav = (ret & XNegative)? GRAV_NEG : GRAV_POS; y_grav = (ret & YNegative)? GRAV_NEG : GRAV_POS; grav = grav_matrix[y_grav][x_grav]; /* Return the values */ if (ret & XValue) { *x_return = x; if (hints != NULL) { hints->x = x; } } if (ret & YValue) { *y_return = y; if (hints != NULL) { hints->y = y; } } if (ret & WidthValue) { *width_return = w; if (hints != NULL) { hints->width = w; } } if (ret & HeightValue) { *height_return = h; if (hints != NULL) { hints->height = h; } } if (1 /*flags & GravityValue*/ && grav != DEFAULT_GRAVITY) { if (hints != NULL && hints->flags & PWinGravity) { hints->win_gravity = grav; } } if (hints != NULL && ret & XValue && ret & YValue) hints->flags |= USPosition; return ret; }
static void __map_window(Display *dpy) { rectangle new_g; rectangle screen_g; Window dummy; fscreen_scr_arg *fsarg = NULL; /* for now no xinerama support */ ftips_placement_t placement; int x,y; static int border_width = 1; static Window win_f = None; if (border_width != current_config->border_width) { XSetWindowBorderWidth(dpy, win, current_config->border_width); border_width = current_config->border_width; } FScreenGetScrRect( fsarg, FSCREEN_GLOBAL, &screen_g.x, &screen_g.y, &screen_g.width, &screen_g.height); new_g.height = ((current_config->Ffont)? current_config->Ffont->height:0) + 1; new_g.width = 4; if (label && current_config->Ffont) { new_g.width += FlocaleTextWidth( current_config->Ffont, label, strlen(label)); } if (current_config->placement != FTIPS_PLACEMENT_AUTO_UPDOWN && current_config->placement != FTIPS_PLACEMENT_AUTO_LEFTRIGHT) { placement = current_config->placement; } else { XTranslateCoordinates( dpy, win_for, DefaultRootWindow(dpy), box.x, box.y, &x, &y, &dummy); if (current_config->placement == FTIPS_PLACEMENT_AUTO_UPDOWN) { if (y + box.height/2 >= screen_g.height/2) { placement = FTIPS_PLACEMENT_UP; } else { placement = FTIPS_PLACEMENT_DOWN; } } else { if (x + box.width/2 >= screen_g.width/2) { placement = FTIPS_PLACEMENT_LEFT; } else { placement = FTIPS_PLACEMENT_RIGHT; } } } if (placement == FTIPS_PLACEMENT_RIGHT || placement == FTIPS_PLACEMENT_LEFT) { if (current_config->justification == FTIPS_JUSTIFICATION_CENTER) { y = box.y + (box.height / 2) - (new_g.height / 2) - current_config->border_width; } else if (current_config->justification == FTIPS_JUSTIFICATION_RIGHT_DOWN) { y = box.y + box.height - new_g.height - (2 * current_config->border_width) - current_config->justification_offset; } else /* LEFT_UP */ { y = box.y + current_config->justification_offset; } } else /* placement == FTIPS_PLACEMENT_DOWN || placement == FTIPS_PLACEMENT_UP */ { if (current_config->justification == FTIPS_JUSTIFICATION_CENTER) { x = box.x + (box.width / 2) - (new_g.width / 2) - current_config->border_width; } else if (current_config->justification == FTIPS_JUSTIFICATION_RIGHT_DOWN) { x = box.x + box.width - new_g.width - (2 * current_config->border_width) - current_config->justification_offset; } else /* LEFT_UP */ { x = box.x + current_config->justification_offset; } } if (placement == FTIPS_PLACEMENT_RIGHT) { x = box.x + box.width + current_config->placement_offset + 1; } else if (placement == FTIPS_PLACEMENT_LEFT) { x = box.x - current_config->placement_offset - new_g.width - (2 * current_config->border_width) - 1; } else if (placement == FTIPS_PLACEMENT_DOWN) { y = box.y + box.height + current_config->placement_offset - 0; } else /* UP */ { y = box.y - current_config->placement_offset - new_g.height + 0 - (2 * current_config->border_width); } XTranslateCoordinates( dpy, win_for, DefaultRootWindow(dpy), x, y, &new_g.x, &new_g.y, &dummy); if (placement == FTIPS_PLACEMENT_RIGHT || placement == FTIPS_PLACEMENT_LEFT) { int x1,y1,l1,l2; if (new_g.x < 2) { x = box.x + box.width + current_config->placement_offset + 1; XTranslateCoordinates( dpy, win_for, DefaultRootWindow(dpy), x, y, &x1, &y1, &dummy); /* */ l1 = new_g.width + new_g.x - 2; l2 = screen_g.width - (x1 + new_g.width) - current_config->border_width - 2; if (l2 > l1) { new_g.x = x1; } } else if (new_g.x + new_g.width > screen_g.width - (2 * current_config->border_width) - 2) { x = box.x - current_config->placement_offset - new_g.width - (2 * current_config->border_width) - 1; XTranslateCoordinates( dpy, win_for, DefaultRootWindow(dpy), x, y, &x1, &y1, &dummy); /* */ l1 = new_g.width + x1 - 2; l2 = screen_g.width - (new_g.x + new_g.width) - (2 * current_config->border_width) - 2; if (l1 > l2) { new_g.x = x1; } } if ( new_g.y < 2 ) { new_g.y = 2; } else if (new_g.y + new_g.height > screen_g.height - (2 * current_config->border_width) - 2) { new_g.y = screen_g.height - new_g.height - (2 * current_config->border_width) - 2; } } else /* placement == FTIPS_PLACEMENT_DOWN || placement == FTIPS_PLACEMENT_UP */ { if (new_g.y < 2) { y = box.y + box.height + current_config->placement_offset - 0; XTranslateCoordinates( dpy, win_for, DefaultRootWindow(dpy), x, y, &new_g.x, &new_g.y, &dummy); } else if (new_g.y + new_g.height > screen_g.height - (2 * current_config->border_width) - 2) { y = box.y - current_config->placement_offset - new_g.height + 0 - (2 * current_config->border_width); XTranslateCoordinates( dpy, win_for, DefaultRootWindow(dpy), x, y, &new_g.x, &new_g.y, &dummy); } if ( new_g.x < 2 ) { new_g.x = 2; } else if (new_g.x + new_g.width > screen_g.width - (2 * current_config->border_width) - 2) { new_g.x = screen_g.width - new_g.width - (2 * current_config->border_width) - 2; } } /* make changes to window */ XMoveResizeWindow( dpy, win, new_g.x, new_g.y, new_g.width, new_g.height); __setup_gc(dpy); if (current_config->colorset > -1) { SetWindowBackground( dpy, win, new_g.width, new_g.height, &Colorset[current_config->colorset], Pdepth, gc, True); } else { XSetWindowBackground (dpy, win, current_config->bg); } if (current_config->border_width > 0) { XSetWindowBorder( dpy, win, Colorset[current_config->colorset].fg); } if (state != FVWM_TIPS_MAPPED && win_f != win_for) { long l_win_for; l_win_for = win_for; XChangeProperty( dpy, win, _net_um_for, XA_WINDOW, 32, PropModeReplace, (unsigned char *) &l_win_for, 1); win_f = win_for; } XMapRaised(dpy, win); state = FVWM_TIPS_MAPPED; return; }