int DrawWindow (void (*DrawWindowContent) (), int (*KeyPressFunction) (int)) { XEvent Event; XWindowAttributes Attr; KeySym nKeySym; int nDepth; if ((prDisplay = XOpenDisplay(0)) == 0) return 1; nScreenNum = DefaultScreen(prDisplay); nWnd = XCreateSimpleWindow(prDisplay, RootWindow(prDisplay,nScreenNum),XPos,YPos,WDef,HDef,WBorder,BlackPixel(prDisplay,nScreenNum),WhitePixel(prDisplay,nScreenNum)); if (SetWindowManagerHints(prDisplay,PClass,nWnd,WMin,HMin,WTitle,WITitle,0)) return 2; XSelectInput(prDisplay, nWnd, ExposureMask | KeyPressMask); XMapWindow(prDisplay, nWnd); prGC = XCreateGC(prDisplay, nWnd, 0, 0); if (AllocColors(prDisplay, DefaultColormap(prDisplay, nScreenNum), &rColors)) return 3; if (CreateBitmaps(prDisplay, nWnd, prPixmap)) return 4; if (XGetWindowAttributes(prDisplay, nWnd, &Attr)) { nWWidth = Attr.width; nWHeight = Attr.height; nDepth = Attr.depth; } else return 5; draw = XCreatePixmap(prDisplay, nWnd, nWWidth, nWHeight, nDepth); if (!draw) return 4; // message cycle while (true) { XNextEvent (prDisplay, &Event); switch (Event.type) { case Expose: // if (! HandleExpose(DrawWindowContent, Event, Attr, nDepth); // ) return 5; break; break; case KeyPress: if (HandleKeyPress(KeyPressFunction, Event, nKeySym)) return 0; break; } while (XCheckMaskEvent(prDisplay, KeyPressMask | KeyReleaseMask, &Event)); } return 0; }
void KeyboardWidget::Setup() { delete[] rcWhite; delete[] rcBlack; DeleteBitmaps(); colorMap.Find("kwup", kclr[0]); colorMap.Find("kwdn", kclr[1]); colorMap.Find("kbup", kclr[2]); colorMap.Find("kbdn", kclr[3]); rcWhite = new wdgRect[whtKeys]; rcBlack = new wdgRect[blkKeys]; // First calculate an appropriate width/height ratio for keys // based on the overall size of the display area. // Start by calculating the width of a key as the // total width divided by the number of keys and the // height as the total height of the window. (We assume // the window is rectangular, wider than high.) A typical // piano keyboard has a ratio of 6/1 for the length // to width of a white key. Thus - if the resulting height // is more than 6 times the width, reduce the height accordingly. // If the resulting height is less than 5 times the width, reduce the // width accordingly. The black keys have a width ratio of app. 7/15 the // size of a white key, but the gaps in between the keys make them appear // wider and we use 7/10 as the ratio to make it look right and give the // user more area to hit with the mouse. Finally, the keyboard is centered // left-right at the top of the window. int widWhite = area.w / whtKeys; int hiWhite = area.h; if (hiWhite > (6*widWhite)) hiWhite = 6*widWhite; else if (hiWhite < (5*widWhite)) widWhite = hiWhite / 5; int hiBlack = (hiWhite * 2) / 3; int widBlack = (widWhite * 7) / 10; int space = (area.w - (widWhite * whtKeys)) / 2; // Pre-calculate the rectangles of the keys. White keys are // equally spaced. Black keys repeat in the 2, 3 pattern with // a gap inbetween the groups equal to the width of a white key. int xWhite = space; int xBlack = space + widWhite - (widBlack / 2); int i, on; int ndxw = 0; int ndxb = 0; for (on = 0; on < octs; on++) { for (i = 0; i < 7; i++) { rcWhite[ndxw].x = (int) xWhite + area.x; rcWhite[ndxw].y = area.y; rcWhite[ndxw].w = (int) widWhite; rcWhite[ndxw].h = hiWhite; xWhite += widWhite; ndxw++; } for (i = 0; i < 2; i++) { rcBlack[ndxb].x = (int) xBlack + area.x; rcBlack[ndxb].y = area.y; rcBlack[ndxb].w = (int) widBlack; rcBlack[ndxb].h = hiBlack; xBlack += widWhite; ndxb++; } xBlack += widWhite; for ( i = 0; i < 3; i++) { rcBlack[ndxb].x = (int) xBlack + area.x; rcBlack[ndxb].y = area.y; rcBlack[ndxb].w = (int) widBlack; rcBlack[ndxb].h = hiBlack; xBlack += widWhite; ndxb++; } xBlack += widWhite; } // pitch class conversion for white and black keys knWhite[0] = 0; knWhite[1] = 2; knWhite[2] = 4; knWhite[3] = 5; knWhite[4] = 7; knWhite[5] = 9; knWhite[6] = 11; knBlack[0] = 1; knBlack[1] = 3; knBlack[2] = 6; knBlack[3] = 8; knBlack[4] = 10; lastKey = -1; rcLastKey = 0; CreateBitmaps(); }