blob: 7e9274def8fe8ab8196ad8b8e523fb6e4f4704d0 [file] [log] [blame]
Dees_Troy51a0e822012-09-05 15:24:24 -04001// base_objects.cpp - Source to manage GUI base objects
2
3#include <stdarg.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <fcntl.h>
8#include <sys/reboot.h>
9#include <sys/stat.h>
10#include <sys/time.h>
11#include <sys/mman.h>
12#include <sys/types.h>
13#include <sys/ioctl.h>
14#include <time.h>
15#include <unistd.h>
16#include <stdlib.h>
17
18#include <string>
19
20extern "C" {
21#include "../common.h"
22#include "../minuitwrp/minui.h"
23#include "../recovery_ui.h"
24}
25
26#include "rapidxml.hpp"
27#include "objects.hpp"
28
29extern int gGuiRunning;
30
31std::map<std::string, PageSet*> PageManager::mPageSets;
32PageSet* PageManager::mCurrentSet;
33PageSet* PageManager::mBaseSet = NULL;
34
35
36// Helper routine to convert a string to a color declaration
37int ConvertStrToColor(std::string str, COLOR* color)
38{
39 // Set the default, solid black
40 memset(color, 0, sizeof(COLOR));
41 color->alpha = 255;
42
43 // Translate variables
44 DataManager::GetValue(str, str);
45
46 // Look for some defaults
47 if (str == "black") return 0;
48 else if (str == "white") { color->red = color->green = color->blue = 255; return 0; }
49 else if (str == "red") { color->red = 255; return 0; }
50 else if (str == "green") { color->green = 255; return 0; }
51 else if (str == "blue") { color->blue = 255; return 0; }
52
53 // At this point, we require an RGB(A) color
54 if (str[0] != '#') return -1;
55 str.erase(0, 1);
56
57 int result = strtol(str.c_str(), NULL, 16);
58 if (str.size() > 6)
59 {
60 // We have alpha channel
61 color->alpha = result & 0x000000FF;
62 result = result >> 8;
63 }
64 color->red = (result >> 16) & 0x000000FF;
65 color->green = (result >> 8) & 0x000000FF;
66 color->blue = result & 0x000000FF;
67 return 0;
68}
69
70// Helper APIs
71bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h /* = NULL */, RenderObject::Placement* placement /* = NULL */)
72{
73 if (!node) return false;
74
75 std::string value;
76 if (node->first_attribute("x"))
77 {
78 value = node->first_attribute("x")->value();
79 DataManager::GetValue(value, value);
80 *x = atol(value.c_str());
81 }
82
83 if (node->first_attribute("y"))
84 {
85 value = node->first_attribute("y")->value();
86 DataManager::GetValue(value, value);
87 *y = atol(value.c_str());
88 }
89
90 if (w && node->first_attribute("w"))
91 {
92 value = node->first_attribute("w")->value();
93 DataManager::GetValue(value, value);
94 *w = atol(value.c_str());
95 }
96
97 if (h && node->first_attribute("h"))
98 {
99 value = node->first_attribute("h")->value();
100 DataManager::GetValue(value, value);
101 *h = atol(value.c_str());
102 }
103
104 if (placement && node->first_attribute("placement"))
105 {
106 value = node->first_attribute("placement")->value();
107 DataManager::GetValue(value, value);
108 *placement = (RenderObject::Placement) atol(value.c_str());
109 }
110
111 return true;
112}
113
114int ActionObject::SetActionPos(int x, int y, int w, int h)
115{
116 if (x < 0 || y < 0) return -1;
117
118 mActionX = x;
119 mActionY = y;
120 if (w || h)
121 {
122 mActionW = w;
123 mActionH = h;
124 }
125 return 0;
126}
127
128Page::Page(xml_node<>* page, xml_node<>* templates /* = NULL */)
129{
130 mTouchStart = NULL;
131
132 // We can memset the whole structure, because the alpha channel is ignored
133 memset(&mBackground, 0, sizeof(COLOR));
134
135 // With NULL, we make a console-only display
136 if (!page)
137 {
138 mName = "console";
139
140 GUIConsole* element = new GUIConsole(NULL);
141 mRenders.push_back(element);
142 mActions.push_back(element);
143 return;
144 }
145
146 if (page->first_attribute("name"))
147 mName = page->first_attribute("name")->value();
148 else
149 {
150 LOGE("No page name attribute found!\n");
151 return;
152 }
153
154 LOGI("Loading page %s\n", mName.c_str());
155
156 // This is a recursive routine for template handling
157 ProcessNode(page, templates);
158
159 return;
160}
161
162bool Page::ProcessNode(xml_node<>* page, xml_node<>* templates /* = NULL */, int depth /* = 0 */)
163{
164 if (depth == 10)
165 {
166 LOGE("Page processing depth has exceeded 10. Failing out. This is likely a recursive template.\n");
167 return false;
168 }
169
170 // Let's retrieve the background value, if any
171 xml_node<>* bg = page->first_node("background");
172 if (bg)
173 {
174 xml_attribute<>* attr = bg->first_attribute("color");
175 if (attr)
176 {
177 std::string color = attr->value();
178 ConvertStrToColor(color, &mBackground);
179 }
180 }
181
182 xml_node<>* child;
183 child = page->first_node("object");
184 while (child)
185 {
186 if (!child->first_attribute("type"))
187 break;
188
189 std::string type = child->first_attribute("type")->value();
190
191 if (type == "text")
192 {
193 GUIText* element = new GUIText(child);
194 mRenders.push_back(element);
195 mActions.push_back(element);
196 }
197 else if (type == "image")
198 {
199 GUIImage* element = new GUIImage(child);
200 mRenders.push_back(element);
201 }
202 else if (type == "fill")
203 {
204 GUIFill* element = new GUIFill(child);
205 mRenders.push_back(element);
206 }
207 else if (type == "action")
208 {
209 GUIAction* element = new GUIAction(child);
210 mActions.push_back(element);
211 }
212 else if (type == "console")
213 {
214 GUIConsole* element = new GUIConsole(child);
215 mRenders.push_back(element);
216 mActions.push_back(element);
217 }
218 else if (type == "button")
219 {
220 GUIButton* element = new GUIButton(child);
221 mRenders.push_back(element);
222 mActions.push_back(element);
223 }
224 else if (type == "checkbox")
225 {
226 GUICheckbox* element = new GUICheckbox(child);
227 mRenders.push_back(element);
228 mActions.push_back(element);
229 }
230 else if (type == "fileselector")
231 {
232 GUIFileSelector* element = new GUIFileSelector(child);
233 mRenders.push_back(element);
234 mActions.push_back(element);
235 }
236 else if (type == "animation")
237 {
238 GUIAnimation* element = new GUIAnimation(child);
239 mRenders.push_back(element);
240 }
241 else if (type == "progressbar")
242 {
243 GUIProgressBar* element = new GUIProgressBar(child);
244 mRenders.push_back(element);
245 mActions.push_back(element);
246 }
247 else if (type == "slider")
248 {
249 GUISlider* element = new GUISlider(child);
250 mRenders.push_back(element);
251 mActions.push_back(element);
252 }
253 else if (type == "listbox")
254 {
255 GUIListBox* element = new GUIListBox(child);
256 mRenders.push_back(element);
257 mActions.push_back(element);
258 }
259 else if (type == "keyboard")
260 {
261 GUIKeyboard* element = new GUIKeyboard(child);
262 mRenders.push_back(element);
263 mActions.push_back(element);
264 }
265 else if (type == "input")
266 {
267 GUIInput* element = new GUIInput(child);
268 mRenders.push_back(element);
269 mActions.push_back(element);
270 mInputs.push_back(element);
271 }
272 else if (type == "template")
273 {
274 if (!templates || !child->first_attribute("name"))
275 {
276 LOGE("Invalid template request.\n");
277 }
278 else
279 {
280 std::string name = child->first_attribute("name")->value();
281
282 // We need to find the correct template
283 xml_node<>* node;
284 node = templates->first_node("template");
285
286 while (node)
287 {
288 if (!node->first_attribute("name"))
289 continue;
290
291 if (name == node->first_attribute("name")->value())
292 {
293 if (!ProcessNode(node, templates, depth + 1))
294 return false;
295 else
296 break;
297 }
298 node = node->next_sibling("template");
299 }
300 }
301 }
302 else
303 {
304 LOGE("Unknown object type.\n");
305 }
306 child = child->next_sibling("object");
307 }
308 return true;
309}
310
311int Page::Render(void)
312{
313 // Render background
314 gr_color(mBackground.red, mBackground.green, mBackground.blue, mBackground.alpha);
315 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
316
317 // Render remaining objects
318 std::vector<RenderObject*>::iterator iter;
319 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
320 {
321 if ((*iter)->Render())
322 LOGE("A render request has failed.\n");
323 }
324 return 0;
325}
326
327int Page::Update(void)
328{
329 int retCode = 0;
330
331 std::vector<RenderObject*>::iterator iter;
332 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
333 {
334 int ret = (*iter)->Update();
335 if (ret < 0)
336 LOGE("An update request has failed.\n");
337 else if (ret > retCode)
338 retCode = ret;
339 }
340
341 return retCode;
342}
343
344int Page::NotifyTouch(TOUCH_STATE state, int x, int y)
345{
346 // By default, return 1 to ignore further touches if nobody is listening
347 int ret = 1;
348
349 // Don't try to handle a lack of handlers
350 if (mActions.size() == 0) return ret;
351
352 // We record mTouchStart so we can pass all the touch stream to the same handler
353 if (state == TOUCH_START)
354 {
355 std::vector<ActionObject*>::reverse_iterator iter;
356 // We work backwards, from top-most element to bottom-most element
357 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
358 {
359 if ((*iter)->IsInRegion(x, y))
360 {
361 mTouchStart = (*iter);
362 ret = mTouchStart->NotifyTouch(state, x, y);
363 if (ret >= 0) break;
364 mTouchStart = NULL;
365 }
366 }
367 }
368 else if (state == TOUCH_RELEASE && mTouchStart != NULL)
369 {
370 ret = mTouchStart->NotifyTouch(state, x, y);
371 mTouchStart = NULL;
372 }
373 else if ((state == TOUCH_DRAG || state == TOUCH_HOLD || state == TOUCH_REPEAT) && mTouchStart != NULL)
374 {
375 ret = mTouchStart->NotifyTouch(state, x, y);
376 }
377 return ret;
378}
379
380int Page::NotifyKey(int key)
381{
382 std::vector<ActionObject*>::reverse_iterator iter;
383
384 // Don't try to handle a lack of handlers
385 if (mActions.size() == 0) return 1;
386
387 // We work backwards, from top-most element to bottom-most element
388 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
389 {
390 int ret = (*iter)->NotifyKey(key);
391 if (ret == 0)
392 return 0;
393 else if (ret < 0)
394 LOGE("An action handler has returned an error");
395 }
396 return 1;
397}
398
399int Page::NotifyKeyboard(int key)
400{
401 std::vector<InputObject*>::reverse_iterator iter;
402
403 // Don't try to handle a lack of handlers
404 if (mInputs.size() == 0) return 1;
405
406 // We work backwards, from top-most element to bottom-most element
407 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
408 {
409 int ret = (*iter)->NotifyKeyboard(key);
410 if (ret == 0)
411 return 0;
412 else if (ret < 0)
413 LOGE("A keyboard handler has returned an error");
414 }
415 return 1;
416}
417
418int Page::SetKeyBoardFocus(int inFocus)
419{
420 std::vector<InputObject*>::reverse_iterator iter;
421
422 // Don't try to handle a lack of handlers
423 if (mInputs.size() == 0) return 1;
424
425 // We work backwards, from top-most element to bottom-most element
426 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
427 {
428 int ret = (*iter)->SetInputFocus(inFocus);
429 if (ret == 0)
430 return 0;
431 else if (ret < 0)
432 LOGE("An input focus handler has returned an error");
433 }
434 return 1;
435}
436
437void Page::SetPageFocus(int inFocus)
438{
439 // Render remaining objects
440 std::vector<RenderObject*>::iterator iter;
441 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
442 {
443 (*iter)->SetPageFocus(inFocus);
444 }
445 return;
446}
447
448int Page::NotifyVarChange(std::string varName, std::string value)
449{
450 std::vector<ActionObject*>::iterator iter;
451
452 // Don't try to handle a lack of handlers
453 if (mActions.size() == 0) return 1;
454
455 for (iter = mActions.begin(); iter != mActions.end(); ++iter)
456 {
457 if ((*iter)->NotifyVarChange(varName, value))
458 LOGE("An action handler errored on NotifyVarChange.\n");
459 }
460 return 0;
461}
462
463PageSet::PageSet(char* xmlFile)
464{
465 mResources = NULL;
466 mCurrentPage = NULL;
467 mOverlayPage = NULL;
468
469 mXmlFile = xmlFile;
470 if (xmlFile)
471 mDoc.parse<0>(mXmlFile);
472 else
473 mCurrentPage = new Page(NULL);
474}
475
476PageSet::~PageSet()
477{
478 delete mResources;
479 free(mXmlFile);
480}
481
482int PageSet::Load(ZipArchive* package)
483{
484 xml_node<>* parent;
485 xml_node<>* child;
486 xml_node<>* templates;
487
488 parent = mDoc.first_node("recovery");
489 if (!parent)
490 parent = mDoc.first_node("install");
491
492 // Now, let's parse the XML
493 LOGI("Loading resources...\n");
494 child = parent->first_node("resources");
495 if (child)
496 mResources = new ResourceManager(child, package);
497
498 LOGI("Loading variables...\n");
499 child = parent->first_node("variables");
500 if (child)
501 LoadVariables(child);
502
503 LOGI("Loading pages...\n");
504 // This may be NULL if no templates are present
505 templates = parent->first_node("templates");
506
507 child = parent->first_node("pages");
508 if (!child)
509 return -1;
510
511 return LoadPages(child, templates);
512}
513
514int PageSet::SetPage(std::string page)
515{
516 Page* tmp = FindPage(page);
517 if (tmp)
518 {
519 if (mCurrentPage) mCurrentPage->SetPageFocus(0);
520 mCurrentPage = tmp;
521 mCurrentPage->SetPageFocus(1);
522 mCurrentPage->NotifyVarChange("", "");
523 return 0;
524 }
525 else
526 {
527 LOGE("Unable to locate page (%s)\n", page.c_str());
528 }
529 return -1;
530}
531
532int PageSet::SetOverlay(Page* page)
533{
534 if (mOverlayPage) mOverlayPage->SetPageFocus(0);
535 mOverlayPage = page;
536 if (mOverlayPage)
537 {
538 mOverlayPage->SetPageFocus(1);
539 mOverlayPage->NotifyVarChange("", "");
540 }
541 return 0;
542}
543
544Resource* PageSet::FindResource(std::string name)
545{
546 return mResources ? mResources->FindResource(name) : NULL;
547}
548
549Page* PageSet::FindPage(std::string name)
550{
551 std::vector<Page*>::iterator iter;
552
553 for (iter = mPages.begin(); iter != mPages.end(); iter++)
554 {
555 if (name == (*iter)->GetName())
556 return (*iter);
557 }
558 return NULL;
559}
560
561int PageSet::LoadVariables(xml_node<>* vars)
562{
563 xml_node<>* child;
564
565 child = vars->first_node("variable");
566 while (child)
567 {
568 if (!child->first_attribute("name"))
569 break;
570 if (!child->first_attribute("value"))
571 break;
572
573 DataManager::SetValue(child->first_attribute("name")->value(), child->first_attribute("value")->value());
574 child = child->next_sibling("variable");
575 }
576 return 0;
577}
578
579int PageSet::LoadPages(xml_node<>* pages, xml_node<>* templates /* = NULL */)
580{
581 xml_node<>* child;
582
583 if (!pages) return -1;
584
585 child = pages->first_node("page");
586 while (child != NULL)
587 {
588 Page* page = new Page(child, templates);
589 if (page->GetName().empty())
590 {
591 LOGE("Unable to process load page\n");
592 delete page;
593 }
594 else
595 {
596 mPages.push_back(page);
597 }
598 child = child->next_sibling("page");
599 }
600 if (mPages.size() > 0)
601 return 0;
602 return -1;
603}
604
605int PageSet::IsCurrentPage(Page* page)
606{
607 return ((mCurrentPage && mCurrentPage == page) ? 1 : 0);
608}
609
610int PageSet::Render(void)
611{
612 int ret;
613
614 ret = (mCurrentPage ? mCurrentPage->Render() : -1);
615 if (ret < 0) return ret;
616 ret = (mOverlayPage ? mOverlayPage->Render() : -1);
617 return ret;
618}
619
620int PageSet::Update(void)
621{
622 int ret;
623
624 ret = (mCurrentPage ? mCurrentPage->Update() : -1);
625 if (ret < 0 || ret > 1) return ret;
626 ret = (mOverlayPage ? mOverlayPage->Update() : -1);
627 return ret;
628}
629
630int PageSet::NotifyTouch(TOUCH_STATE state, int x, int y)
631{
632 if (mOverlayPage) return (mOverlayPage->NotifyTouch(state, x, y));
633 return (mCurrentPage ? mCurrentPage->NotifyTouch(state, x, y) : -1);
634}
635
636int PageSet::NotifyKey(int key)
637{
638 if (mOverlayPage) return (mOverlayPage->NotifyKey(key));
639 return (mCurrentPage ? mCurrentPage->NotifyKey(key) : -1);
640}
641
642int PageSet::NotifyKeyboard(int key)
643{
644 if (mOverlayPage) return (mOverlayPage->NotifyKeyboard(key));
645 return (mCurrentPage ? mCurrentPage->NotifyKeyboard(key) : -1);
646}
647
648int PageSet::SetKeyBoardFocus(int inFocus)
649{
650 if (mOverlayPage) return (mOverlayPage->SetKeyBoardFocus(inFocus));
651 return (mCurrentPage ? mCurrentPage->SetKeyBoardFocus(inFocus) : -1);
652}
653
654int PageSet::NotifyVarChange(std::string varName, std::string value)
655{
656 if (mOverlayPage) mOverlayPage->NotifyVarChange(varName, value);
657 return (mCurrentPage ? mCurrentPage->NotifyVarChange(varName, value) : -1);
658}
659
660int PageManager::LoadPackage(std::string name, std::string package, std::string startpage)
661{
662 int fd;
663 ZipArchive zip, *pZip = NULL;
664 long len;
665 char* xmlFile = NULL;
666 PageSet* pageSet = NULL;
667 int ret;
668
669 // Open the XML file
670 LOGI("Loading package: %s (%s)\n", name.c_str(), package.c_str());
671 if (mzOpenZipArchive(package.c_str(), &zip))
672 {
673 // We can try to load the XML directly...
674 struct stat st;
675 if(stat(package.c_str(),&st) != 0)
676 return -1;
677
678 len = st.st_size;
679 xmlFile = (char*) malloc(len + 1);
680 if (!xmlFile) return -1;
681
682 fd = open(package.c_str(), O_RDONLY);
683 if (fd == -1) goto error;
684
685 read(fd, xmlFile, len);
686 close(fd);
687 }
688 else
689 {
690 pZip = &zip;
691 const ZipEntry* ui_xml = mzFindZipEntry(&zip, "ui.xml");
692 if (ui_xml == NULL)
693 {
694 LOGE("Unable to locate ui.xml in zip file\n");
695 goto error;
696 }
697
698 // Allocate the buffer for the file
699 len = mzGetZipEntryUncompLen(ui_xml);
700 xmlFile = (char*) malloc(len + 1);
701 if (!xmlFile) goto error;
702
703 if (!mzExtractZipEntryToBuffer(&zip, ui_xml, (unsigned char*) xmlFile))
704 {
705 LOGE("Unable to extract ui.xml\n");
706 goto error;
707 }
708 }
709
710 // NULL-terminate the string
711 xmlFile[len] = 0x00;
712
713 // Before loading, mCurrentSet must be the loading package so we can find resources
714 pageSet = mCurrentSet;
715 mCurrentSet = new PageSet(xmlFile);
716
717 ret = mCurrentSet->Load(pZip);
718 if (ret == 0)
719 {
720 mCurrentSet->SetPage(startpage);
721 mPageSets.insert(std::pair<std::string, PageSet*>(name, mCurrentSet));
722 }
723 else
724 {
725 LOGE("Package %s failed to load.\n", name.c_str());
726 }
727
728 // The first successful package we loaded is the base
729 if (mBaseSet == NULL)
730 mBaseSet = mCurrentSet;
731
732 mCurrentSet = pageSet;
733
734 if (pZip) mzCloseZipArchive(pZip);
735 return ret;
736
737error:
738 LOGE("An internal error has occurred.\n");
739 if (pZip) mzCloseZipArchive(pZip);
740 if (xmlFile) free(xmlFile);
741 return -1;
742}
743
744PageSet* PageManager::FindPackage(std::string name)
745{
746 std::map<std::string, PageSet*>::iterator iter;
747
748 iter = mPageSets.find(name);
749 if (iter != mPageSets.end())
750 {
751 return (*iter).second;
752 }
753 LOGE("Unable to locate package %s\n", name.c_str());
754 return NULL;
755}
756
757PageSet* PageManager::SelectPackage(std::string name)
758{
759 LOGI("Switching packages (%s)\n", name.c_str());
760 PageSet* tmp;
761
762 tmp = FindPackage(name);
763 if (tmp)
764 mCurrentSet = tmp;
765 else
766 LOGE("Unable to find package.\n");
767
768 return mCurrentSet;
769}
770
771int PageManager::ReloadPackage(std::string name, std::string package)
772{
773 std::map<std::string, PageSet*>::iterator iter;
774
775 iter = mPageSets.find(name);
776 if (iter == mPageSets.end())
777 return -1;
778
779 PageSet* set = (*iter).second;
780 mPageSets.erase(iter);
781
782 if (LoadPackage(name, package, "main") != 0)
783 {
784 LOGE("Failed to load package.\n");
785 mPageSets.insert(std::pair<std::string, PageSet*>(name, set));
786 return -1;
787 }
788 if (mCurrentSet == set) SelectPackage(name);
789 delete set;
790 return 0;
791}
792
793void PageManager::ReleasePackage(std::string name)
794{
795 std::map<std::string, PageSet*>::iterator iter;
796
797 iter = mPageSets.find(name);
798 if (iter == mPageSets.end())
799 return;
800
801 PageSet* set = (*iter).second;
802 mPageSets.erase(iter);
803 delete set;
804 return;
805}
806
807int PageManager::ChangePage(std::string name)
808{
809 DataManager::SetValue("tw_operation_state", 0);
810 int ret = (mCurrentSet ? mCurrentSet->SetPage(name) : -1);
811 return ret;
812}
813
814int PageManager::ChangeOverlay(std::string name)
815{
816 if (name.empty())
817 return mCurrentSet->SetOverlay(NULL);
818 else
819 {
820 Page* page = mBaseSet ? mBaseSet->FindPage(name) : NULL;
821 return mCurrentSet->SetOverlay(page);
822 }
823}
824
825Resource* PageManager::FindResource(std::string name)
826{
827 return (mCurrentSet ? mCurrentSet->FindResource(name) : NULL);
828}
829
830Resource* PageManager::FindResource(std::string package, std::string name)
831{
832 PageSet* tmp;
833
834 tmp = FindPackage(name);
835 return (tmp ? tmp->FindResource(name) : NULL);
836}
837
838int PageManager::SwitchToConsole(void)
839{
840 PageSet* console = new PageSet(NULL);
841
842 mCurrentSet = console;
843 return 0;
844}
845
846int PageManager::IsCurrentPage(Page* page)
847{
848 return (mCurrentSet ? mCurrentSet->IsCurrentPage(page) : 0);
849}
850
851int PageManager::Render(void)
852{
853 return (mCurrentSet ? mCurrentSet->Render() : -1);
854}
855
856int PageManager::Update(void)
857{
858 return (mCurrentSet ? mCurrentSet->Update() : -1);
859}
860
861int PageManager::NotifyTouch(TOUCH_STATE state, int x, int y)
862{
863 return (mCurrentSet ? mCurrentSet->NotifyTouch(state, x, y) : -1);
864}
865
866int PageManager::NotifyKey(int key)
867{
868 return (mCurrentSet ? mCurrentSet->NotifyKey(key) : -1);
869}
870
871int PageManager::NotifyKeyboard(int key)
872{
873 return (mCurrentSet ? mCurrentSet->NotifyKeyboard(key) : -1);
874}
875
876int PageManager::SetKeyBoardFocus(int inFocus)
877{
878 return (mCurrentSet ? mCurrentSet->SetKeyBoardFocus(inFocus) : -1);
879}
880
881int PageManager::NotifyVarChange(std::string varName, std::string value)
882{
883 return (mCurrentSet ? mCurrentSet->NotifyVarChange(varName, value) : -1);
884}
885
886extern "C" void gui_notifyVarChange(const char *name, const char* value)
887{
888 if (!gGuiRunning) return;
889
890 PageManager::NotifyVarChange(name, value);
891}
892