#include #include #include #include static int gravities[10] = { NorthWestGravity, NorthGravity, NorthEastGravity, WestGravity, CenterGravity, EastGravity, SouthWestGravity, SouthGravity, SouthEastGravity, StaticGravity }; typedef struct { int x, y, width, height; } Rectangle; static Window windows[10]; static int doubled[10] = { 0, }; static Rectangle window_rects[10]; #define WINDOW_WIDTH 100 #define WINDOW_HEIGHT 100 static int x_offset[3] = { 0, - WINDOW_WIDTH/2, -WINDOW_WIDTH }; static int y_offset[3] = { 0, - WINDOW_HEIGHT/2, -WINDOW_HEIGHT }; static double screen_x_fraction[3] = { 0, 0.5, 1.0 }; static double screen_y_fraction[3] = { 0, 0.5, 1.0 }; static int screen_width; static int screen_height; static const char* window_gravity_to_string (int gravity) { switch (gravity) { case NorthWestGravity: return "NorthWestGravity"; case NorthGravity: return "NorthGravity"; case NorthEastGravity: return "NorthEastGravity"; case WestGravity: return "WestGravity"; case CenterGravity: return "CenterGravity"; case EastGravity: return "EastGravity"; case SouthWestGravity: return "SouthWestGravity"; case SouthGravity: return "SouthGravity"; case SouthEastGravity: return "SouthEastGravity"; case StaticGravity: return "StaticGravity"; default: return "NorthWestGravity"; } } static void calculate_position (int i, int is_doubled, int *x, int *y) { if (i == 9) { *x = 150; *y = 150; } else { int xoff = x_offset[i % 3]; int yoff = y_offset[i / 3]; if (is_doubled) { xoff *= 2; yoff *= 2; } *x = (int) (screen_x_fraction[i % 3] * (double) screen_width) + xoff; *y = (int) (screen_y_fraction[i / 3] * (double) screen_height) + yoff; } } static int find_window (Window window) { int i; for (i=0; i<10; i++) { if (windows[i] == window) return i; } return -1; } typedef struct { unsigned long flags; unsigned long functions; unsigned long decorations; long input_mode; unsigned long status; } MotifWmHints, MwmHints; #define MWM_HINTS_FUNCTIONS (1L << 0) #define MWM_HINTS_DECORATIONS (1L << 1) #define MWM_HINTS_INPUT_MODE (1L << 2) #define MWM_HINTS_STATUS (1L << 3) int main (int argc, char **argv) { Display *d; Window w; XSizeHints hints; int i; int screen; XEvent ev; int noframes; if (argc > 1 && strcmp (argv[1], "--noframes") == 0) noframes = 1; else noframes = 0; d = XOpenDisplay (NULL); screen = DefaultScreen (d); screen_width = DisplayWidth (d, screen); screen_height = DisplayHeight (d, screen); for (i=0; i<10; i++) { int x, y; calculate_position (i, doubled[i], &x, &y); w = XCreateSimpleWindow (d, RootWindow (d, screen), x, y, WINDOW_WIDTH, WINDOW_HEIGHT, 0, WhitePixel (d, screen), WhitePixel (d, screen)); windows[i] = w; window_rects[i].x = x; window_rects[i].y = y; window_rects[i].width = WINDOW_WIDTH; window_rects[i].height = WINDOW_HEIGHT; XSelectInput (d, w, ButtonPressMask | ExposureMask | StructureNotifyMask); hints.flags = USPosition | PMinSize | PMaxSize | PWinGravity; hints.min_width = WINDOW_WIDTH / 2; hints.min_height = WINDOW_HEIGHT / 2; #if 1 /* we constrain max size below the "doubled" size so that * the WM will have to deal with constraints * at the same time it's dealing with configure request */ hints.max_width = WINDOW_WIDTH * 2 - WINDOW_WIDTH / 2; hints.max_height = WINDOW_HEIGHT * 2 - WINDOW_HEIGHT / 2; #else hints.max_width = WINDOW_WIDTH * 2 + WINDOW_WIDTH / 2; hints.max_height = WINDOW_HEIGHT * 2 + WINDOW_HEIGHT / 2; #endif hints.win_gravity = gravities[i]; XSetWMNormalHints (d, w, &hints); XStoreName (d, w, window_gravity_to_string (hints.win_gravity)); if (noframes) { MotifWmHints mwm; Atom mwm_atom; mwm.decorations = 0; mwm.flags = MWM_HINTS_DECORATIONS; mwm_atom = XInternAtom (d, "_MOTIF_WM_HINTS", False); XChangeProperty (d, w, mwm_atom, mwm_atom, 32, PropModeReplace, (unsigned char *)&mwm, sizeof (MotifWmHints)/sizeof (long)); } XMapWindow (d, w); } while (1) { XNextEvent (d, &ev); if (ev.xany.type == ConfigureNotify) { i = find_window (ev.xconfigure.window); if (i >= 0) { Window ignored; window_rects[i].width = ev.xconfigure.width; window_rects[i].height = ev.xconfigure.height; XClearArea (d, windows[i], 0, 0, ev.xconfigure.width, ev.xconfigure.height, True); if (!ev.xconfigure.send_event) XTranslateCoordinates (d, windows[i], DefaultRootWindow (d), 0, 0, &window_rects[i].x, &window_rects[i].y, &ignored); else { window_rects[i].x = ev.xconfigure.x; window_rects[i].y = ev.xconfigure.y; } } } else if (ev.xany.type == Expose) { i = find_window (ev.xexpose.window); if (i >= 0) { GC gc; XGCValues values; char buf[256]; values.foreground = BlackPixel (d, screen); gc = XCreateGC (d, windows[i], GCForeground, &values); sprintf (buf, "%d,%d", window_rects[i].x, window_rects[i].y); XDrawString (d, windows[i], gc, 10, 15, buf, strlen (buf)); sprintf (buf, "%dx%d", window_rects[i].width, window_rects[i].height); XDrawString (d, windows[i], gc, 10, 35, buf, strlen (buf)); XFreeGC (d, gc); } } else if (ev.xany.type == ButtonPress) { i = find_window (ev.xbutton.window); if (i >= 0) { /* Button 1 = move, 2 = resize, 3 = both at once */ if (ev.xbutton.button == Button1) { int x, y; calculate_position (i, doubled[i], &x, &y); XMoveWindow (d, windows[i], x, y); } else if (ev.xbutton.button == Button2) { if (doubled[i]) XResizeWindow (d, windows[i], WINDOW_WIDTH, WINDOW_HEIGHT); else XResizeWindow (d, windows[i], WINDOW_WIDTH*2, WINDOW_HEIGHT*2); doubled[i] = !doubled[i]; } else if (ev.xbutton.button == Button3) { int x, y; calculate_position (i, !doubled[i], &x, &y); if (doubled[i]) XMoveResizeWindow (d, windows[i], x, y, WINDOW_WIDTH, WINDOW_HEIGHT); else XMoveResizeWindow (d, windows[i], x, y, WINDOW_WIDTH*2, WINDOW_HEIGHT*2); doubled[i] = !doubled[i]; } } } } /* This program has an infinite loop above so a return statement would * just cause compiler warnings. */ }