Jump to content

All Activity

This stream auto-updates

  1. Today
  2. Yesterday
  3. Last week
  4. Earlier
  5. As I noted earlier, The _gwinFlushRedraws function contains two branches: "Do loss of visibility first" and "Do the visible windows next". The first branch is for hiding the window. The second branch is for drawing windows with visibility flags set. When a window needs to be hidden, the GWIN_FLG_BGREDRAW flag is set, which is processed in the corresponding branch of the WM_Redraw function. A check is performed, does the window have a parent? If there is a parent, then this parent needs to be redrawed. If there is no parent, then there is nothing to redraw. In my opinion, the logic is as follows. The windows that need to be shown are processed in the second branch of the _gwinFlushRedraws function. Based on this reasoning, I modified the code as follows and marked this places with the label ">>": static void WM_Redraw(GHandle gh) { gU32 flags; >> gU32 parents = 0; flags = gh->flags; gh->flags &= ~(GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW|GWIN_FLG_PARENTREVEAL); #if GWIN_NEED_CONTAINERS redo_redraw: #endif if ((flags & GWIN_FLG_SYSVISIBLE)) { if (gh->vmt->Redraw) gh->vmt->Redraw(gh); else if ((flags & GWIN_FLG_BGREDRAW)) { // We can't redraw but we want full coverage so just clear the area gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor); // Only do an after clear if this is not a parent reveal if (!(flags & GWIN_FLG_PARENTREVEAL) && gh->vmt->AfterClear) gh->vmt->AfterClear(gh); } #if GWIN_NEED_CONTAINERS // If this is container but not a parent reveal, mark any visible children for redraw // We redraw our children here as we have overwritten them in redrawing the parent // as GDISP/GWIN doesn't support complex clipping regions. if ((flags & (GWIN_FLG_CONTAINER|GWIN_FLG_PARENTREVEAL)) == GWIN_FLG_CONTAINER) { // Container redraw is done for(gh = gwinGetFirstChild(gh); gh; gh = gwinGetSibling(gh)) _gwinUpdate(gh); return; } #endif } else { if ((flags & GWIN_FLG_BGREDRAW)) { GHandle gx; #if GWIN_NEED_CONTAINERS if (gh->parent) { // Child redraw is done >> parents++; // Get the parent to redraw the area gh = gh->parent; // The parent is already marked for redraw - don't do it now. if ((gh->flags & GWIN_FLG_NEEDREDRAW)) return; // Use the existing clipping region and redraw now gh->flags |= (GWIN_FLG_BGREDRAW|GWIN_FLG_PARENTREVEAL); goto redo_redraw; } #endif // Clear the area to the background color gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor()); >> #if GWIN_NEED_CONTAINERS >> if (!parents) return; >> #endif // Now loop over all windows looking for overlaps. Redraw them if they overlap the newly exposed area. for(gx = gwinGetNextWindow(0); gx; gx = gwinGetNextWindow(gx)) { if ((gx->flags & GWIN_FLG_SYSVISIBLE) && gx->display == gh->display && gx->x < gh->x+gh->width && gx->y < gh->y+gh->height && gx->x+gx->width >= gh->x && gx->y+gx->height >= gh->y) { if (gx->vmt->Redraw) gx->vmt->Redraw(gx); else // We can't redraw this window but we want full coverage so just clear the area gdispGFillArea(gx->display, gx->x, gx->y, gx->width, gx->height, gx->bgcolor); } } } } } I introduced an additional variable that indicates whether the window has a parent. If there is no parent, then no redrawing occurs. If there is a parent, then it will be redrawed either in this function or later. The gx variable is an auxiliary variable-pointer to an object in the list. Therefore, any setting of flags in this variable is meaningless. I think this code meets your expectations. With this code, redrawing occurs only once.
  6. Hmm. I don't think that is right, and even if it is works it will make the redraw require 2 redraw cycles to work. I think the problem is the bottom gdispGFillArea that is using gx. Whilst WM_Redraw clears any pending drawing operations, the gdispGFillArea doesn't and it should in this case. Try putting back the original code and then changing that bottom gdispGFillArea to... <code> else { gdispGFillArea(gx.... gx->flags &= ~(GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW|GWIN_FLG_PARENTREVEAL); } </code> The other area I pointed out is also probably still a bug but that one needs more testing.
  7. I modified the WM_Redraw function code as follows and the double redrawing does not occur. if ((flags & GWIN_FLG_BGREDRAW)) { GHandle gx; #if GWIN_NEED_CONTAINERS if (gh->parent) { // Child redraw is done // Get the parent to redraw the area gh = gh->parent; // The parent is already marked for redraw - don't do it now. if ((gh->flags & GWIN_FLG_NEEDREDRAW)) return; // Use the existing clipping region and redraw now gh->flags |= (GWIN_FLG_BGREDRAW|GWIN_FLG_PARENTREVEAL); goto redo_redraw; -> }else{ -> gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor()); -> return; } #endif // Clear the area to the background color gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor());
  8. This code is executed only if the window has a parent. In my case, the container and tabset do not have parents. Therefore, the code is not executed and the code immediately switches to executing first the area clearing, and then searching for windows with visibility flags set and redrawing them. I previously marked this place with the label "3==>".
  9. Hmm. I can see what might be a bug that you can try... <code> gh->flags |= (GWIN_FLG_BGREDRAW|GWIN_FLG_PARENTREVEAL); goto redo_redraw; </code> As the flags are saved before the redo_redraw label, I think modifying the gh->flags is probably a bug. It should perhaps just read "flags |= ...". Give that change a try and let me know if it helps.
  10. I continued my research. The _gwinFlushRedraws function handles hiding the window in the "Do loss of visibility first" branch. The GWIN_FLG_NEEDREDRAW and GWIN_FLG_SYSVISIBLE flags are checked for all windows. If the GWIN_FLG_SYSVISIBLE flag is set, the window does not require hiding and its redrawing is ignored. I marked this place with the "1==>" label. If redrawing is required, i.e. the GWIN_FLG_NEEDREDRAW flag is set and GWIN_FLG_SYSVISIBLE is cleared, then the GWINwm->vmt->Redraw(gh) function is called. I marked this place with the "2==>" label. void _gwinFlushRedraws(GRedrawMethod how) { GHandle gh; // Do we really need to do anything? if (!RedrawPending) return; // Obtain the drawing lock if (how == REDRAW_WAIT) gfxSemWait(&gwinsem, gDelayForever); else if (how == REDRAW_NOWAIT && !gfxSemWait(&gwinsem, gDelayNone)) // Someone is drawing - They will do the redraw when they are finished return; // Do loss of visibility first while ((RedrawPending & DOREDRAW_INVISIBLES)) { RedrawPending &= ~DOREDRAW_INVISIBLES; // Catch new requests for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) { 1==> if ((gh->flags & (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) != GWIN_FLG_NEEDREDRAW) continue; // Do the redraw #if GDISP_NEED_CLIP gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height); 2==> _GWINwm->vmt->Redraw(gh); gdispGUnsetClip(gh->display); #else _GWINwm->vmt->Redraw(gh); #endif // Postpone further redraws #if !GWIN_REDRAW_IMMEDIATE && !GWIN_REDRAW_SINGLEOP ... The GWINwm->vmt->Redraw(gh) function also has two branches of rendering. The first branch renders the window if the GWIN_FLG_SYSVISIBLE flag is set. The second branch either does nothing or, if the GWIN_FLG_BGREDRAW flag is set, clears the area and renders windows that have the GWIN_FLG_SYSVISIBLE flag set. This is where the next window is called when the previous one is hidden. I marked this place with the label "3==>". static void WM_Redraw(GHandle gh) { gU32 flags; flags = gh->flags; gh->flags &= ~(GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW|GWIN_FLG_PARENTREVEAL); #if GWIN_NEED_CONTAINERS redo_redraw: #endif if ((flags & GWIN_FLG_SYSVISIBLE)) { if (gh->vmt->Redraw) gh->vmt->Redraw(gh); else if ((flags & GWIN_FLG_BGREDRAW)) { // We can't redraw but we want full coverage so just clear the area gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor); // Only do an after clear if this is not a parent reveal if (!(flags & GWIN_FLG_PARENTREVEAL) && gh->vmt->AfterClear) gh->vmt->AfterClear(gh); } #if GWIN_NEED_CONTAINERS // If this is container but not a parent reveal, mark any visible children for redraw // We redraw our children here as we have overwritten them in redrawing the parent // as GDISP/GWIN doesn't support complex clipping regions. if ((flags & (GWIN_FLG_CONTAINER|GWIN_FLG_PARENTREVEAL)) == GWIN_FLG_CONTAINER) { // Container redraw is done for(gh = gwinGetFirstChild(gh); gh; gh = gwinGetSibling(gh)) _gwinUpdate(gh); return; } #endif } else { if ((flags & GWIN_FLG_BGREDRAW)) { GHandle gx; #if GWIN_NEED_CONTAINERS if (gh->parent) { // Child redraw is done // Get the parent to redraw the area gh = gh->parent; // The parent is already marked for redraw - don't do it now. if ((gh->flags & GWIN_FLG_NEEDREDRAW)) return; // Use the existing clipping region and redraw now gh->flags |= (GWIN_FLG_BGREDRAW|GWIN_FLG_PARENTREVEAL); goto redo_redraw; } #endif // Clear the area to the background color gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor()); // Now loop over all windows looking for overlaps. Redraw them if they overlap the newly exposed area. 3==> for(gx = gwinGetNextWindow(0); gx; gx = gwinGetNextWindow(gx)) { if ((gx->flags & GWIN_FLG_SYSVISIBLE) && gx->display == gh->display && gx->x < gh->x+gh->width && gx->y < gh->y+gh->height && gx->x+gx->width >= gh->x && gx->y+gx->height >= gh->y) { if (gx->vmt->Redraw) gx->vmt->Redraw(gx); else // We can't redraw this window but we want full coverage so just clear the area gdispGFillArea(gx->display, gx->x, gx->y, gx->width, gx->height, gx->bgcolor); } } } } } I believe this is due to the specific implementation of the concept of separating the change of window rendering flags in one operating system thread and the rendering process itself in another thread.
  11. It has been a long time since I looked at the code but... It should be possible to retest the visibility flag in the invisible loop. If the window is now visible don't redraw it because it will get redrawn later.
  12. I went through the debugger and figured out the logic of the window manager. The _gwinFlushRedraws function contains two branches: "Do loss of visibility first" and "Do the visible windows next". The new window is redrawn twice, here's why. The first time as a hidden window, but the visibility flag is already set. The second time as a window that is visible. It turns out that we need to somehow make it so that the new window is not redrawn as invisible. Is it possible to do this?
  13. Looking at the video, whenever you swap screens (using either button) it is doing the double drawing. It is much more visible with the tab with the list because font drawing is relatively slow, but it is also happening when you switch to the button screen. uGFX's window manager is really dumb because the drawing engine doesn't support multiple clip areas, which means it struggles with overlapping Windows. That can often lead to double draw operations. The reason the tab control doesn't have this issue is because the control code itself understands exactly how the tab pages overlap and therefore optimises its drawing for that Check if when you are switching between the tab window and the button window that you are hiding the old window before making the new window visible so that there is only one visible full screen page at any time. I hope that helps
  14. Hello! I recorded a video The screen is redrawn more than once. I did not find the reason for this phenomenon quickly. I need help. When uGFX is initialized, screen elements are formed in the usual way, nothing extra. At the beginning, when you press the button, the screen with the button is hidden and a function is called that makes the screen with TabSet visible. case GEVENT_GWIN_BUTTON: ///(GEVENT_GWIN_CTRL_FIRST+0) if (((GEventGWinButton*)pe)->gwin == mainProductButton) { gwinHide(mainContainer); _ghActiveScreen = productScreenShow(); } GHandle productScreenShow(void) { productScreenUpdate(); gwinShow(prodTabset); return prodTabset; } Clicking on tabs only causes one screen repaint. See video. When returning to the previous screen, it is redrawn twice. I set a breakpoint on the gwinTabsetDraw_Std function and got this call stack: What should be done to make the screen redrawn once? The screen is redrawn more than once.mp4
  15. For local use this solution seems logical.
  16. Also, there is another problem that has not been discussed in this thread. I would like to share it with you. Given that we have a lot of keyboard layouts, there is some problem, if we click on the button to increase the characters once and select and click the desired character (in my case, either Ukrainian or Russian layout), the layout will reset to English. I also solved this problem, and the file is located in ugfx/src/gwin/gwin/gwin_keybord.c Line about 213 and the method KeyMouseUp. The contents of the code itself: I was commenting on what I changed // A mouse up has occurred (it may or may not be over the button) static void KeyMouseUp(GWidgetObject *gw, gCoord x, gCoord y) { #define gk ((GKeyboardObject *)gw) KeyFindKey(gk, x, y); // Do we have a valid key? if (gk->keyrow == GKEY_BAD_ROWCOL) { if (gk->lastkeyrow != GKEY_BAD_ROWCOL) { gw->g.flags |= GKEYBOARD_FLG_QUICKUPDATE; _gwinUpdate((GHandle)gw); } return; } // We are turning off the display of the key gk->keyrow = gk->keycol = GKEY_BAD_ROWCOL; // Is this one of the special keys if (gk->key < 0x20) { // This is a special key const GVSpecialKey *skey; skey = &gk->keytable->skeys[gk->key - 1]; if ((skey->flags & GVKEY_SINGLESET)) { // Single character switch to a new layout gk->keyset = gk->keytable->ksets[skey->newset]; gk->w.g.flags &= ~(GKEYBOARD_FLG_QUICKUPDATE|GKEYBOARD_FLG_REVERTSET); gk->w.g.flags |= GKEYBOARD_FLG_REVERTSET; } else if ((skey->flags & GVKEY_LOCKSET)) { // Locked switch to a new layout gk->keyset = gk->keytable->ksets[skey->newset]; gk->w.g.flags &= ~(GKEYBOARD_FLG_QUICKUPDATE|GKEYBOARD_FLG_REVERTSET); } else if ((gk->w.g.flags & GKEYBOARD_FLG_REVERTSET)) { // Revert to default layout // **Фикс:** Сбрасываем только регистр, не меняя раскладку if (gk->keyset == gk->keytable->ksets[6]) { gk->keyset = gk->keytable->ksets[5]; // Русский регистр вниз } else if (gk->keyset == gk->keytable->ksets[9]) { gk->keyset = gk->keytable->ksets[8]; // Украинский регистр вниз } else { gk->keyset = gk->keytable->ksets[0]; // Английский регистр вниз } gk->w.g.flags &= ~(GKEYBOARD_FLG_QUICKUPDATE|GKEYBOARD_FLG_REVERTSET); } else { // Just turning off a key gw->g.flags |= GKEYBOARD_FLG_QUICKUPDATE; } // Send the key if required if (skey->sendkey && skey->sendkey[0]) SendVirtualKeyEvent(gk); // Update the display _gwinUpdate((GHandle)gw); return; } // Do we need to revert to the standard layout? if ((gk->w.g.flags & GKEYBOARD_FLG_REVERTSET)) { // **Фикс:** Сбрасываем только регистр, не меняя раскладку if (gk->keyset == gk->keytable->ksets[6]) { gk->keyset = gk->keytable->ksets[5]; // Русский регистр вниз } else if (gk->keyset == gk->keytable->ksets[9]) { gk->keyset = gk->keytable->ksets[8]; // Украинский регистр вниз } else { gk->keyset = gk->keytable->ksets[0]; // Английский регистр вниз } gk->w.g.flags &= ~(GKEYBOARD_FLG_QUICKUPDATE|GKEYBOARD_FLG_REVERTSET); } else { gw->g.flags |= GKEYBOARD_FLG_QUICKUPDATE; } // Send the key SendVirtualKeyEvent(gk); // Update the display _gwinUpdate((GHandle)gw); }
  17. I also added another keyboard layout (Ukrainian). Maybe someone will need it: #if GWIN_NEED_KEYBOARD_ENGLISH1 /* For this keyboard mapping we use: * Set 0 = Lowercase letters * Set 1 = Uppercase letters (transient) * Set 2 = Uppercase letters (locked) * Set 3 = Numbers * Set 4 = Symbols */ static const GVSpecialKey Eng1SKeys[] = { { "\001", 0, GVKEY_SINGLESET, 1 }, // \001 (1) = Shift Lower to Upper { "\001", 0, GVKEY_INVERT|GVKEY_LOCKSET, 2 }, // \002 (2) = Shift Upper to Upper Lock { "\002", 0, GVKEY_INVERT|GVKEY_LOCKSET, 0}, // \003 (3) = Shift Upper Lock to Lower { "123", 0, GVKEY_LOCKSET, 3 }, // \004 (4) = Change to Numbers { "\010", "\b", 0, 0 }, // \005 (5) = Backspace { "\015", "\r", 0, 0 }, // \006 (6) = Enter 1 { "\015", "\r", 0, 0 }, // \007 (7) = Enter 2 (Short keycap) { "Sym", 0, GVKEY_LOCKSET, 4 }, // \010 (8) = Change to Symbols { "aA", 0, GVKEY_LOCKSET, 0 }, // \011 (9) = Change to Lower Alphab { "RU", 0, GVKEY_LOCKSET, 5 }, // \012 (10) = Change to Russian { "UA", 0, GVKEY_LOCKSET, 8 }, // \013 (11) = Change to Ukrainian { "EN", 0, GVKEY_LOCKSET, 0 }, // \014 (12) = Change to English { "\001", 0, GVKEY_SINGLESET, 6 }, // \015 (13) = Shift Lower to Upper { "\001", 0, GVKEY_INVERT|GVKEY_LOCKSET, 7 }, // \016 (14) = Shift Upper to Upper Lock { "\002", 0, GVKEY_INVERT|GVKEY_LOCKSET, 5 }, // \017 (15) = Shift Upper Lock to Lower { "\001", 0, GVKEY_SINGLESET, 9 }, // \020 (16) = Shift Lower to Upper { "\001", 0, GVKEY_INVERT|GVKEY_LOCKSET, 10 }, // \021 (17) = Shift Upper to Upper Lock { "\002", 0, GVKEY_INVERT|GVKEY_LOCKSET, 8 } // \022 (18) = Shift Upper Lock to Lower }; static const char Eng1Set0Row3[] = "\004\012 .\006\006"; static const char Ru1Set0Row3[] = "\004\013 .\006\006"; static const char Ua1Set0Row3[] = "\004\014 .\006\006"; static const char Eng1Set1Row0[] = "QWERTYUIOP"; static const char Eng1Set1Row1[] = "ASDFGHJKL"; static const char Ru1Set1Row0[] = "ЙЦУКЕНГШЩЗХЪ"; static const char Ru1Set1Row1[] = "ФЫВАПРОЛДЖЭ"; static const char Ua1Set1Row0[] = "ЙЦУКЕНГШЩЗХЇ"; static const char Ua1Set1Row1[] = "ФІВАПРОЛДЖЄ"; static const char *Eng1Set0[] = { "qwertyuiop", "asdfghjkl", "\001zxcvbnm\005", Eng1Set0Row3, 0 }; static const char *Eng1Set1[] = { Eng1Set1Row0, Eng1Set1Row1, "\002ZXCVBNM\005", Eng1Set0Row3, 0 }; static const char *Eng1Set2[] = { Eng1Set1Row0, Eng1Set1Row1, "\003ZXCVBNM\005", Eng1Set0Row3, 0 }; static const char *Eng1Set3[] = { "+-*/", "@789", "\007456", "\010123", "\01100.", 0 }; static const char *Eng1Set4[] = { "#$%^&*()", "~`:;\"'{}", "<>?/\\|[]", "\011\004,! .@", 0 }; static const char *Rus1Set0[] = { "йцукенгшщзхъ", "фывапролджэ", "\015ячсмитьбю\005", Ru1Set0Row3, 0 }; static const char *Rus1Set1[] = { Ru1Set1Row0, Ru1Set1Row1, "\016ЯЧСМИТЬБЮ\005", Ru1Set0Row3, 0 }; static const char *Rus1Set2[] = { Ru1Set1Row0, Ru1Set1Row1, "\017ЯЧСМИТЬБЮ\005", Ru1Set0Row3, 0 }; static const char *Ukr1Set0[] = { "йцукенгшщзхї", "фівапролджє", "\020ячсмитьбюґ\005", Ua1Set0Row3, 0 }; static const char *Ukr1Set1[] = { Ua1Set1Row0, Ua1Set1Row1, "\021ЯЧСМИТЬБЮҐ\005", Ua1Set0Row3, 0 }; static const char *Ukr1Set2[] = { Ua1Set1Row0, Ua1Set1Row1, "\022ЯЧСМИТЬБЮҐ\005", Ua1Set0Row3, 0 }; static const GVKeySet Eng1Sets[] = { Eng1Set0, Eng1Set1, Eng1Set2, Eng1Set3, Eng1Set4, Rus1Set0, Rus1Set1, Rus1Set2, Ukr1Set0, Ukr1Set1, Ukr1Set2, 0 }; const GVKeyTable VirtualKeyboard_English1 = { Eng1SKeys, Eng1Sets }; #endif // GWIN_NEED_KEYBOARD_ENGLISH1
  18. Hello, I was able to rework the character removal method, it now works with both Cyrillic and English. The modified file is located at ugfx/src/gwin/gwin_textedit.c The method that needs to be modified is on line 30 called TextEditRemoveChar. The content of the code itself: static void TextEditRemoveChar(GHandle gh) { char *p; const char *q; unsigned sz, pos, charStart; if (!gh || !gh2obj->w.text) return; sz = strlen(gh2obj->w.text); pos = gh2obj->cursorPos; if (pos > sz) pos = gh2obj->cursorPos = sz; // Определяем начало символа в UTF-8 charStart = pos; while (charStart > 0 && (gh2obj->w.text[charStart] & 0xC0) == 0x80) { charStart--; } // Проверка, является ли символ многобайтовым (UTF-8) int isMultibyte = (gh2obj->w.text[charStart] & 0x80) != 0; q = gh2obj->w.text + pos; if (!(gh->flags & GWIN_FLG_ALLOCTXT)) { // Выделяем память и копируем строку if (!(p = gfxAlloc(sz))) return; if (isMultibyte) { // Удаление многобайтового символа memcpy(p, gh2obj->w.text, charStart); memcpy(p + charStart, q + (pos - charStart), sz - pos); } else { // Удаление однобайтового символа memcpy(p, gh2obj->w.text, pos); memcpy(p + pos, q + 1, sz - pos); } gh->flags |= GWIN_FLG_ALLOCTXT; } else { if (isMultibyte) { // Удаление многобайтового символа с сдвигом memmove((char *)gh2obj->w.text + charStart, q + (pos - charStart), sz - pos); p = gfxRealloc((char *)gh2obj->w.text, sz + 1, sz - (pos - charStart) + 1); } else { // Удаление однобайтового символа с сдвигом memmove((char *)q, q + 1, sz - pos); p = gfxRealloc((char *)gh2obj->w.text, sz + 1, sz); } if (!p) return; } gh2obj->w.text = p; gh2obj->cursorPos = charStart; // Перемещаем курсор }
  19. Yes, the existing keyboard action for backspace is not multi-byte language aware. If someone would like to submit a patch to make it utf-8 aware, that would be great.
  20. Hello! The language support problem in this case can be solved in two ways. The first is to use, for example, encoding 866 with Cyrillic support or ISO/IEC 8859-5. also known as the fifth sets of the ISO/IEC 8859 8-bit character encoding. The second is intended for UTF-8 and is solved by modifying the TextEditRemoveChar method of the TextEdit widget by adding analysis of the removed character.
  21. Hello again, yes I was able to figure out what was wrong thanks to Sergei. But now there is another problem, when deleting Cyrillic characters (and we know that the Cyrillic character is two bytes of memory) the programme deletes not completely the character (i.e. one byte). How can this be cured? I will be grateful for your help! #include "gfx.h" #include "/home/office-nivki/Documents/projects/resources/ugfx/src/gwin/gwin_keyboard_layout.h" static const GVSpecialKey Eng1SKeys[] = { { "\001", 0, GVKEY_SINGLESET, 1 }, // \001 (1) = Shift Lower to Upper { "\001", 0, GVKEY_INVERT|GVKEY_LOCKSET, 2 }, // \002 (2) = Shift Upper to Upper Lock { "\002", 0, GVKEY_INVERT|GVKEY_LOCKSET, 0 }, // \003 (3) = Shift Upper Lock to Lower { "123", 0, GVKEY_LOCKSET, 3 }, // \004 (4) = Change to Numbers { "\010", "\b", 0, 0 }, // \005 (5) = Backspace { "\015", "\r", 0, 0 }, // \006 (6) = Enter 1 { "\015", "\r", 0, 0 }, // \007 (7) = Enter 2 (Short keycap) { "Sym", 0, GVKEY_LOCKSET, 4 }, // \010 (8) = Change to Symbols { "aA", 0, GVKEY_LOCKSET, 0 }, // \011 (9) = Change to Lower Alpha { "RU", 0, GVKEY_LOCKSET, 5 }, // \012 (10) = Change to Lower Alpha { "EN", 0, GVKEY_LOCKSET, 0 }, // \013 (11) = Change to Lower Alpha { "\001", 0, GVKEY_SINGLESET, 6 }, // \014 (12) = Shift Lower to Upper { "\001", 0, GVKEY_INVERT|GVKEY_LOCKSET, 7 }, // \015 (13) = Shift Upper to Upper Lock { "\002", 0, GVKEY_INVERT|GVKEY_LOCKSET, 5 }, // \016 (14) = Shift Upper Lock to Lower }; static const char Eng1Set0Row3[] = "\004\012 .\006\006"; static const char Ru1Set0Row3[] = "\004\004\013 .\006\006"; static const char Eng1Set1Row0[] = "QWERTYUIOP"; static const char Eng1Set1Row1[] = "ASDFGHJKL"; static const char Ru1Set1Row0[] = "ЙЦУКЕНГШЩЗХЪ"; static const char Ru1Set1Row1[] = "ФЫВАПРОЛДЖЭ"; static const char *Eng1Set0[] = { "qwertyuiop", "asdfghjkl", "\001zxcvbnm\005", Eng1Set0Row3, 0 }; static const char *Eng1Set1[] = { Eng1Set1Row0, Eng1Set1Row1, "\002ZXCVBNM\005", Eng1Set0Row3, 0 }; static const char *Eng1Set2[] = { Eng1Set1Row0, Eng1Set1Row1, "\003ZXCVBNM\005", Eng1Set0Row3, 0 }; static const char *Eng1Set3[] = { "+-*/", "@789", "\007456", "\010123", "\01100.", 0 }; static const char *Eng1Set4[] = { "#$%^&*()", "~`:;\"'{}", "<>?/\\|[]", "\011\004,! .@", 0 }; static const char *Rus1Set0[] = { "йцукенгшщзхъ", "фывапролджэ", "\014ячсмитьбю\005", Ru1Set0Row3, 0 }; static const char *Rus1Set1[] = { Ru1Set1Row0, Ru1Set1Row1, "\015ЯЧСМИТЬБЮ\005", Ru1Set0Row3, 0 }; static const char *Rus1Set2[] = { Ru1Set1Row0, Ru1Set1Row1, "\016ЯЧСМИТЬБЮ\005", Ru1Set0Row3, 0 }; static const GVKeySet Eng1Sets[] = { Eng1Set0, Eng1Set1, Eng1Set2, Eng1Set3, Eng1Set4, Rus1Set0, Rus1Set1, Rus1Set2, 0 }; const GVKeyTable VirtualKeyboard_EnRu1 = { Eng1SKeys, Eng1Sets }; static GListener gl; static GHandle ghTextedit1; static GHandle ghTextedit2; static GHandle ghTextedit3; static GHandle KeyboardNum; static void guiCreate(void) { GWidgetInit wi; gwinWidgetClearInit(&wi); // TextEdit1 wi.g.show = gTrue; wi.g.x = 10; wi.g.y = 20; wi.g.width = 200; wi.g.height = 35; wi.text = "Use the TAB key"; ghTextedit1 = gwinTexteditCreate(0, &wi, 100); // TextEdit2 wi.g.show = gTrue; wi.g.x = 10; wi.g.y = 100; wi.g.width = 200; wi.g.height = 35; wi.text = "to switch between"; ghTextedit2 = gwinTexteditCreate(0, &wi, 20); // TextEdit3 wi.g.show = gTrue; wi.g.x = 10; wi.g.y = 180; wi.g.width = 200; wi.g.height = 35; wi.text = "the different widgets"; ghTextedit3 = gwinTexteditCreate(0, &wi, 100); // Virtual keyboard wi.g.show = gTrue; wi.g.x = 0; wi.g.y = (gdispGetHeight()/2); wi.g.width = gdispGetWidth(); wi.g.height = gdispGetHeight()/2; wi.text = "KeybNum"; KeyboardNum = gwinKeyboardCreate(0, &wi); gwinKeyboardSetLayout(KeyboardNum, &VirtualKeyboard_EnRu1); // We also want to listen to keyboard events from the virtual keyboard geventAttachSource(&gl, gwinKeyboardGetEventSource(KeyboardNum), GLISTEN_KEYTRANSITIONS|GLISTEN_KEYUP); } int main(void) { gfxInit(); gdispClear(GFX_SILVER); gwinSetDefaultFont(gdispOpenFont("MontserratRegular16")); gwinSetDefaultStyle(&WhiteWidgetStyle, gFalse); gwinSetDefaultColor(GFX_BLACK); gwinSetDefaultBgColor(GFX_WHITE); geventListenerInit(&gl); geventAttachSource(&gl, ginputGetKeyboard(0), 0); guiCreate(); while(1) { gfxSleepMilliseconds(500); } }
  22. Could you provide some more details? I had no problems compiling the code. Did you forget the inclusion of gwin/gwin_keyboard_layout.h or enabling the options in gfxconf.h? Please share your full build output.
  23. Hello & Welcome to the µGFX community! µGFX accesses display hardware via the so-called "board file". Each display driver has a file named board_xxx_template.h where xxx is the driver name. In your case, that would be /drivers/gdisp/ILI9341/board_ILI9341_template.h. Simply copy that file to your project and rename it to board_ILI9341.h. In that file, you will find the various functions the driver needs to access on the hardware/peripherals to talk to the display controller - you'll have to implement those functions to work with your ecosystem (i.e. Arduino) and your hardware. So technically, that is where the pin assignments go. You can find an example under boards/addons/gdisp/board_ILI9341_spi.h While that is written to work with ChibiOS, it should still give you an idea of what you need to do (toggle GPIOs, make SPI transactions etc). As for the repository you linked - That seems to be 10 years old. I am not saying it won't work, but also from an understanding/learning perspective, it might be best if you start from scratch and import whatever you need. Please don't hesitate to ask if you have any questions - we're happy to help wherever we can.
  24. I found a piece of a code // Fonts font_t open_sans24,open_sans28; // Слушатель событий GListener glistener; GHandle ghKeyboard, ghConsole1; GEvent* pe; GEventKeyboard * pk; void guiCreate(void) { GWidgetInit wi; // Apply some default values for GWIN gwinWidgetClearInit(&wi); wi.g.show = TRUE; // Prepare fonts - #define GDISP_INCLUDE_FONT_DEJAVUSANSxx TRUE - reqd in gfxconf.h) open_sans24 = gdispOpenFont("open_sans24"); open_sans28 = gdispOpenFont("open_sans28"); // Создаем "слушателя" события geventListenerInit(&glistener); geventAttachSource(&glistener, ginputGetMouse(0), GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEMETA); gwinAttachListener(&glistener); // Устанавливаем дефолтные стили GUI gwinSetDefaultFont(open_sans24);//DejaVuSans20 gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE); // Create the keyboard wi.g.show = gTrue; wi.g.x = 0; wi.g.y = gdispGetHeight()/2; wi.g.width = gdispGetWidth(); wi.g.height = gdispGetHeight()/2; ghKeyboard = gwinKeyboardCreate(0, &wi); gwinKeyboardSetLayout(ghKeyboard, &VirtualKeyboard_EnRu1); gwinSetFont(ghKeyboard, open_sans28); // We also want to listen to keyboard events from the virtual keyboard geventAttachSource(&glistener, gwinKeyboardGetEventSource(ghKeyboard), GLISTEN_KEYTRANSITIONS|GLISTEN_KEYUP); // Create console widget: ghConsole1 wi.g.parent = ghPage1; wi.g.show = TRUE; wi.g.x = 300; wi.g.y = 2; wi.g.width = 700; wi.g.height = 290; wi.text = "Ready"; wi.customParam = 0; wi.customStyle = 0; ghConsole1 = gwinConsoleCreate(0, &wi.g); gwinSetFont(ghConsole1, dejavu_sans_12); gwinSetColor(ghConsole1, Black); gwinSetBgColor(ghConsole1, HTML2COLOR(0xd2d2d2)); gwinShow(ghConsole1); gwinClear(ghConsole1); } ...... while (1) { // Get an Event pe = geventEventWait(&glistener, 1000); switch(pe->type) { case GEVENT_GWIN_KEYBOARD: ///(GEVENT_GWIN_CTRL_FIRST+6) // This is a widget event generated on the standard gwin event source gwinPrintf(ghConsole1, "Keyboard visibility has changed\n"); break; case GEVENT_KEYBOARD: // This is a keyboard event from a keyboard source which must be separately listened to. // It is not sent on the gwin event source even though in this case it was generated by a gwin widget. pk = (GEventKeyboard *)pe; gwinPrintf(ghConsole1, "KEYSTATE: 0x%04X [ %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s]", pk->keystate, (!pk->keystate ? "NONE " : ""), ((pk->keystate & GKEYSTATE_KEYUP) ? "KEYUP " : ""), ((pk->keystate & GKEYSTATE_REPEAT) ? "REPEAT " : ""), ((pk->keystate & GKEYSTATE_SPECIAL) ? "SPECIAL " : ""), ((pk->keystate & GKEYSTATE_RAW) ? "RAW " : ""), ((pk->keystate & GKEYSTATE_SHIFT_L) ? "LSHIFT " : ""), ((pk->keystate & GKEYSTATE_SHIFT_R) ? "RSHIFT " : ""), ((pk->keystate & GKEYSTATE_CTRL_L) ? "LCTRL " : ""), ((pk->keystate & GKEYSTATE_CTRL_R) ? "RCTRL " : ""), ((pk->keystate & GKEYSTATE_ALT_L) ? "LALT " : ""), ((pk->keystate & GKEYSTATE_ALT_R) ? "RALT " : ""), ((pk->keystate & GKEYSTATE_FN) ? "FN " : ""), ((pk->keystate & GKEYSTATE_COMPOSE) ? "COMPOSE " : ""), ((pk->keystate & GKEYSTATE_WINKEY) ? "WINKEY " : ""), ((pk->keystate & GKEYSTATE_CAPSLOCK) ? "CAPSLOCK " : ""), ((pk->keystate & GKEYSTATE_NUMLOCK) ? "NUMLOCK " : ""), ((pk->keystate & GKEYSTATE_SCROLLLOCK) ? "SCROLLLOCK " : "") ); if (pk->bytecount) { gwinPrintf(ghConsole1, " Keys:"); for (i = 0; i < pk->bytecount; i++) gwinPrintf(ghConsole1, " 0x%02X", (int)(gU8)pk->c[i]); gwinPrintf(ghConsole1, " ["); for (i = 0; i < pk->bytecount; i++) gwinPrintf(ghConsole1, "%c", pk->c[i] >= ' ' && pk->c[i] <= '~' ? pk->c[i] : ' '); gwinPrintf(ghConsole1, "]"); } gwinPrintf(ghConsole1, "\n"); break; } }
  25. GHandle KeyboardNum; // Create the keyboard GWidgetInit wi; gwinWidgetClearInit(&wi); wi.g.show = gTrue; wi.g.x = 200; wi.g.y = 185; wi.g.width = 660; wi.g.height = 240; wi.text = "KeybNum"; KeyboardNum = gwinKeyboardCreate(0, &wi); gwinKeyboardSetLayout(KeyboardNum, &VirtualKeyboard_Num); gwinSetFont(KeyboardNum, dejavu_sans_con28); // We also want to listen to keyboard events from the virtual keyboard geventAttachSource(&glistener, gwinKeyboardGetEventSource(KeyboardNum), GLISTEN_KEYTRANSITIONS|GLISTEN_KEYUP);
  26. Excuse me, but could you tell me how to use your code (i.e. as I understand I need to modify the file gwin_keyboard_layout.c by adding your code there). I would like to know how you use it in your programme, I used as a test the sample file, which is in the library itself. Would you mind showing me a piece of code with the application?
  27. /* * This file is subject to the terms of the GFX License. If a copy of * the license was not distributed with this file, you can obtain one at: * * http://ugfx.io/license.html */ #include "../../gfx.h" #if GFX_USE_GWIN && GWIN_NEED_KEYBOARD #include "gwin_keyboard_layout.h" #if GWIN_NEED_KEYBOARD_ENGLISH1 /* For this keyboard mapping we use: * Set 0 = Lowercase letters * Set 1 = Uppercase letters (transient) * Set 2 = Uppercase letters (locked) * Set 3 = Numbers * Set 4 = Symbols */ static const GVSpecialKey Eng1SKeys[] = { { "\001", 0, GVKEY_SINGLESET, 1 }, // \001 (1) = Shift Lower to Upper { "\001", 0, GVKEY_INVERT|GVKEY_LOCKSET, 2 }, // \002 (2) = Shift Upper to Upper Lock { "\002", 0, GVKEY_INVERT|GVKEY_LOCKSET, 0 }, // \003 (3) = Shift Upper Lock to Lower { "123", 0, GVKEY_LOCKSET, 3 }, // \004 (4) = Change to Numbers { "\010", "\b", 0, 0 }, // \005 (5) = Backspace { "\015", "\r", 0, 0 }, // \006 (6) = Enter 1 { "\015", "\r", 0, 0 }, // \007 (7) = Enter 2 (Short keycap) { "Sym", 0, GVKEY_LOCKSET, 4 }, // \010 (8) = Change to Symbols { "aA", 0, GVKEY_LOCKSET, 0 }, // \011 (9) = Change to Lower Alpha }; static const char Eng1Set0Row3[] = "\004 .\006\006"; static const char Eng1Set1Row0[] = "QWERTYUIOP"; static const char Eng1Set1Row1[] = "ASDFGHJKL"; static const char *Eng1Set0[] = { "qwertyuiop", "asdfghjkl", "\001zxcvbnm\005", Eng1Set0Row3, 0 }; static const char *Eng1Set1[] = { Eng1Set1Row0, Eng1Set1Row1, "\002ZXCVBNM\005", Eng1Set0Row3, 0 }; static const char *Eng1Set2[] = { Eng1Set1Row0, Eng1Set1Row1, "\003ZXCVBNM\005", Eng1Set0Row3, 0 }; static const char *Eng1Set3[] = { "+-*/", "@789", "\007456", "\010123", "\01100.", 0 }; static const char *Eng1Set4[] = { "#$%^&*()", "~`:;\"'{}", "<>?/\\|[]", "\011\004,! .@", 0 }; static const GVKeySet Eng1Sets[] = { Eng1Set0, Eng1Set1, Eng1Set2, Eng1Set3, Eng1Set4, 0 }; const GVKeyTable VirtualKeyboard_English1 = { Eng1SKeys, Eng1Sets }; #endif // GWIN_NEED_KEYBOARD_ENGLISH1 #if GWIN_NEED_KEYBOARD_EN_RU1 /* For this keyboard mapping we use: * Set 0 = Lowercase letters * Set 1 = Uppercase letters (transient) * Set 2 = Uppercase letters (locked) * Set 3 = Numbers * Set 4 = Symbols */ static const GVSpecialKey Eng1SKeys[] = { { "\001", 0, GVKEY_SINGLESET, 1 }, // \001 (1) = Shift Lower to Upper { "\001", 0, GVKEY_INVERT|GVKEY_LOCKSET, 2 }, // \002 (2) = Shift Upper to Upper Lock { "\002", 0, GVKEY_INVERT|GVKEY_LOCKSET, 0 }, // \003 (3) = Shift Upper Lock to Lower { "123", 0, GVKEY_LOCKSET, 3 }, // \004 (4) = Change to Numbers { "\010", "\b", 0, 0 }, // \005 (5) = Backspace { "\015", "\r", 0, 0 }, // \006 (6) = Enter 1 { "\015", "\r", 0, 0 }, // \007 (7) = Enter 2 (Short keycap) { "Sym", 0, GVKEY_LOCKSET, 4 }, // \010 (8) = Change to Symbols { "aA", 0, GVKEY_LOCKSET, 0 }, // \011 (9) = Change to Lower Alpha { "RU", 0, GVKEY_LOCKSET, 5 }, // \012 (10) = Change to Lower Alpha { "EN", 0, GVKEY_LOCKSET, 0 }, // \013 (11) = Change to Lower Alpha { "\001", 0, GVKEY_SINGLESET, 6 }, // \014 (12) = Shift Lower to Upper { "\001", 0, GVKEY_INVERT|GVKEY_LOCKSET, 7 }, // \015 (13) = Shift Upper to Upper Lock { "\002", 0, GVKEY_INVERT|GVKEY_LOCKSET, 5 }, // \016 (14) = Shift Upper Lock to Lower }; static const char Eng1Set0Row3[] = "\004\012 .\006\006"; static const char Ru1Set0Row3[] = "\004\004\013 .\006\006"; static const char Eng1Set1Row0[] = "QWERTYUIOP"; static const char Eng1Set1Row1[] = "ASDFGHJKL"; static const char Ru1Set1Row0[] = "ЙЦУКЕНГШЩЗХЪ"; static const char Ru1Set1Row1[] = "ФЫВАПРОЛДЖЭ"; static const char *Eng1Set0[] = { "qwertyuiop", "asdfghjkl", "\001zxcvbnm\005", Eng1Set0Row3, 0 }; static const char *Eng1Set1[] = { Eng1Set1Row0, Eng1Set1Row1, "\002ZXCVBNM\005", Eng1Set0Row3, 0 }; static const char *Eng1Set2[] = { Eng1Set1Row0, Eng1Set1Row1, "\003ZXCVBNM\005", Eng1Set0Row3, 0 }; static const char *Eng1Set3[] = { "+-*/", "@789", "\007456", "\010123", "\01100.", 0 }; static const char *Eng1Set4[] = { "#$%^&*()", "~`:;\"'{}", "<>?/\\|[]", "\011\004,! .@", 0 }; static const char *Rus1Set0[] = { "йцукенгшщзхъ", "фывапролджэ", "\014ячсмитьбю\005", Ru1Set0Row3, 0 }; static const char *Rus1Set1[] = { Ru1Set1Row0, Ru1Set1Row1, "\015ЯЧСМИТЬБЮ\005", Ru1Set0Row3, 0 }; static const char *Rus1Set2[] = { Ru1Set1Row0, Ru1Set1Row1, "\016ЯЧСМИТЬБЮ\005", Ru1Set0Row3, 0 }; static const GVKeySet Eng1Sets[] = { Eng1Set0, Eng1Set1, Eng1Set2, Eng1Set3, Eng1Set4, Rus1Set0, Rus1Set1, Rus1Set2, 0 }; const GVKeyTable VirtualKeyboard_EnRu1 = { Eng1SKeys, Eng1Sets }; #endif // GWIN_NEED_KEYBOARD_ENGLISH1 #if GWIN_NEED_KEYBOARD_NUM /* For this keyboard mapping we use: * Set 0 = Lowercase letters * Set 1 = Uppercase letters (transient) * Set 2 = Uppercase letters (locked) * Set 3 = Numbers * Set 4 = Symbols */ static const GVSpecialKey NumSKeys[] = { { "\001", 0, GVKEY_SINGLESET, 1 }, // \001 (1) = Shift Lower to Upper { "\001", 0, GVKEY_INVERT|GVKEY_LOCKSET, 2 }, // \002 (2) = Shift Upper to Upper Lock { "\002", 0, GVKEY_INVERT|GVKEY_LOCKSET, 0 }, // \003 (3) = Shift Upper Lock to Lower { "123", 0, GVKEY_LOCKSET, 3 }, // \004 (4) = Change to Numbers { "\010", "\b", 0, 0 }, // \005 (5) = Backspace { "\015", "\r", 0, 0 }, // \006 (6) = Enter 1 { "\015", "\r", 0, 0 }, // \007 (7) = Enter 2 (Short keycap) { "Sym", 0, GVKEY_LOCKSET, 4 }, // \010 (8) = Change to Symbols { "aA", 0, GVKEY_LOCKSET, 0 }, // \011 (9) = Change to Lower Alpha { "RU", 0, GVKEY_LOCKSET, 5 }, // \012 (10) = Change to Lower Alpha { "EN", 0, GVKEY_LOCKSET, 0 }, // \013 (11) = Change to Lower Alpha { "\001", 0, GVKEY_SINGLESET, 6 }, // \014 (12) = Shift Lower to Upper { "\001", 0, GVKEY_INVERT|GVKEY_LOCKSET, 7 }, // \015 (13) = Shift Upper to Upper Lock { "\002", 0, GVKEY_INVERT|GVKEY_LOCKSET, 5 }, // \016 (14) = Shift Upper Lock to Lower { "ESC", "\x1b", 0, 0 }, // \017 (15) = Escape }; static const char *NumSet3[] = { "789\017", "456-", "123\005", "00.\007", 0 }; static const GVKeySet NumSets[] = { NumSet3, 0 }; const GVKeyTable VirtualKeyboard_Num = { NumSKeys, NumSets }; #endif // GWIN_NEED_KEYBOARD_ENGLISH1 #endif // GFX_USE_GWIN && GWIN_NEED_KEYBOARD It is my code for keyboards
  1. Load more activity
×
×
  • Create New...