panel.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. /* SLiM - Simple Login Manager
  2. Copyright (C) 1997, 1998 Per Liden
  3. Copyright (C) 2004-06 Simone Rota <sip@varlock.com>
  4. Copyright (C) 2004-06 Johannes Winkelmann <jw@tks6.net>
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. */
  10. #include <sstream>
  11. #include "panel.h"
  12. using namespace std;
  13. Panel::Panel(Display* dpy, int scr, Window root, Cfg* config,
  14. const string& themedir) {
  15. // Set display
  16. Dpy = dpy;
  17. Scr = scr;
  18. Root = root;
  19. cfg = config;
  20. session = "";
  21. // Init GC
  22. XGCValues gcv;
  23. unsigned long gcm;
  24. gcm = GCForeground|GCBackground|GCGraphicsExposures;
  25. gcv.foreground = GetColor("black");
  26. gcv.background = GetColor("white");
  27. gcv.graphics_exposures = False;
  28. TextGC = XCreateGC(Dpy, Root, gcm, &gcv);
  29. font = XftFontOpenName(Dpy, Scr, cfg->getOption("input_font").c_str());
  30. welcomefont = XftFontOpenName(Dpy, Scr, cfg->getOption("welcome_font").c_str());
  31. introfont = XftFontOpenName(Dpy, Scr, cfg->getOption("intro_font").c_str());
  32. enterfont = XftFontOpenName(Dpy, Scr, cfg->getOption("username_font").c_str());
  33. msgfont = XftFontOpenName(Dpy, Scr, cfg->getOption("msg_font").c_str());
  34. Visual* visual = DefaultVisual(Dpy, Scr);
  35. Colormap colormap = DefaultColormap(Dpy, Scr);
  36. // NOTE: using XftColorAllocValue() would be a better solution. Lazy me.
  37. XftColorAllocName(Dpy, visual, colormap, cfg->getOption("input_color").c_str(), &inputcolor);
  38. XftColorAllocName(Dpy, visual, colormap, cfg->getOption("input_shadow_color").c_str(), &inputshadowcolor);
  39. XftColorAllocName(Dpy, visual, colormap, cfg->getOption("welcome_color").c_str(), &welcomecolor);
  40. XftColorAllocName(Dpy, visual, colormap, cfg->getOption("welcome_shadow_color").c_str(), &welcomeshadowcolor);
  41. XftColorAllocName(Dpy, visual, colormap, cfg->getOption("username_color").c_str(), &entercolor);
  42. XftColorAllocName(Dpy, visual, colormap, cfg->getOption("username_shadow_color").c_str(), &entershadowcolor);
  43. XftColorAllocName(Dpy, visual, colormap, cfg->getOption("msg_color").c_str(), &msgcolor);
  44. XftColorAllocName(Dpy, visual, colormap, cfg->getOption("msg_shadow_color").c_str(), &msgshadowcolor);
  45. XftColorAllocName(Dpy, visual, colormap, cfg->getOption("intro_color").c_str(), &introcolor);
  46. // Load properties from config / theme
  47. input_name_x = Cfg::string2int(cfg->getOption("input_name_x").c_str());
  48. input_name_y = Cfg::string2int(cfg->getOption("input_name_y").c_str());
  49. input_pass_x = Cfg::string2int(cfg->getOption("input_pass_x").c_str());
  50. input_pass_y = Cfg::string2int(cfg->getOption("input_pass_y").c_str());
  51. inputShadowXOffset =
  52. Cfg::string2int(cfg->getOption("input_shadow_xoffset").c_str());
  53. inputShadowYOffset =
  54. Cfg::string2int(cfg->getOption("input_shadow_yoffset").c_str());
  55. if (input_pass_x < 0 || input_pass_y < 0){ // single inputbox mode
  56. input_pass_x = input_name_x;
  57. input_pass_y = input_name_y;
  58. }
  59. // Load panel and background image
  60. string panelpng = "";
  61. panelpng = panelpng + themedir +"/panel.png";
  62. image = new Image;
  63. bool loaded = image->Read(panelpng.c_str());
  64. if (!loaded) { // try jpeg if png failed
  65. panelpng = themedir + "/panel.jpg";
  66. loaded = image->Read(panelpng.c_str());
  67. if (!loaded) {
  68. cerr << APPNAME
  69. << ": could not load panel image for theme '"
  70. << basename((char*)themedir.c_str()) << "'"
  71. << endl;
  72. exit(ERR_EXIT);
  73. }
  74. }
  75. Image* bg = new Image();
  76. string bgstyle = cfg->getOption("background_style");
  77. if (bgstyle != "color") {
  78. panelpng = themedir +"/background.png";
  79. loaded = bg->Read(panelpng.c_str());
  80. if (!loaded) { // try jpeg if png failed
  81. panelpng = themedir + "/background.jpg";
  82. loaded = bg->Read(panelpng.c_str());
  83. if (!loaded){
  84. cerr << APPNAME
  85. << ": could not load background image for theme '"
  86. << basename((char*)themedir.c_str()) << "'"
  87. << endl;
  88. exit(ERR_EXIT);
  89. }
  90. }
  91. }
  92. if (bgstyle == "stretch") {
  93. bg->Resize(XWidthOfScreen(ScreenOfDisplay(Dpy, Scr)), XHeightOfScreen(ScreenOfDisplay(Dpy, Scr)));
  94. } else if (bgstyle == "tile") {
  95. bg->Tile(XWidthOfScreen(ScreenOfDisplay(Dpy, Scr)), XHeightOfScreen(ScreenOfDisplay(Dpy, Scr)));
  96. } else if (bgstyle == "center") {
  97. string hexvalue = cfg->getOption("background_color");
  98. hexvalue = hexvalue.substr(1,6);
  99. bg->Center(XWidthOfScreen(ScreenOfDisplay(Dpy, Scr)),
  100. XHeightOfScreen(ScreenOfDisplay(Dpy, Scr)),
  101. hexvalue.c_str());
  102. } else { // plain color or error
  103. string hexvalue = cfg->getOption("background_color");
  104. hexvalue = hexvalue.substr(1,6);
  105. bg->Center(XWidthOfScreen(ScreenOfDisplay(Dpy, Scr)),
  106. XHeightOfScreen(ScreenOfDisplay(Dpy, Scr)),
  107. hexvalue.c_str());
  108. }
  109. string cfgX = cfg->getOption("input_panel_x");
  110. string cfgY = cfg->getOption("input_panel_y");
  111. X = Cfg::absolutepos(cfgX, XWidthOfScreen(ScreenOfDisplay(Dpy, Scr)), image->Width());
  112. Y = Cfg::absolutepos(cfgY, XHeightOfScreen(ScreenOfDisplay(Dpy, Scr)), image->Height());
  113. // Merge image into background
  114. image->Merge(bg, X, Y);
  115. delete bg;
  116. PanelPixmap = image->createPixmap(Dpy, Scr, Root);
  117. // Read (and substitute vars in) the welcome message
  118. welcome_message = cfg->getWelcomeMessage();
  119. intro_message = cfg->getOption("intro_msg");
  120. }
  121. Panel::~Panel() {
  122. XftColorFree (Dpy, DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr), &inputcolor);
  123. XftColorFree (Dpy, DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr), &msgcolor);
  124. XftColorFree (Dpy, DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr), &welcomecolor);
  125. XftColorFree (Dpy, DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr), &entercolor);
  126. XFreeGC(Dpy, TextGC);
  127. XftFontClose(Dpy, font);
  128. XftFontClose(Dpy, msgfont);
  129. XftFontClose(Dpy, introfont);
  130. XftFontClose(Dpy, welcomefont);
  131. XftFontClose(Dpy, enterfont);
  132. delete image;
  133. }
  134. void Panel::OpenPanel() {
  135. // Create window
  136. Win = XCreateSimpleWindow(Dpy, Root, X, Y,
  137. image->Width(),
  138. image->Height(),
  139. 0, GetColor("white"), GetColor("white"));
  140. // Events
  141. XSelectInput(Dpy, Win, ExposureMask | KeyPressMask);
  142. // Set background
  143. XSetWindowBackgroundPixmap(Dpy, Win, PanelPixmap);
  144. // Show window
  145. XMapWindow(Dpy, Win);
  146. XMoveWindow(Dpy, Win, X, Y); // override wm positioning (for tests)
  147. // Grab keyboard
  148. XGrabKeyboard(Dpy, Win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
  149. XFlush(Dpy);
  150. }
  151. void Panel::ClosePanel() {
  152. XUngrabKeyboard(Dpy, CurrentTime);
  153. XUnmapWindow(Dpy, Win);
  154. XDestroyWindow(Dpy, Win);
  155. XFlush(Dpy);
  156. }
  157. void Panel::ClearPanel() {
  158. session = "";
  159. Reset();
  160. XClearWindow(Dpy, Root);
  161. XClearWindow(Dpy, Win);
  162. Cursor(SHOW);
  163. ShowText();
  164. XFlush(Dpy);
  165. }
  166. void Panel::Message(const string& text) {
  167. string cfgX, cfgY;
  168. XGlyphInfo extents;
  169. XftDraw *draw = XftDrawCreate(Dpy, Root,
  170. DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
  171. XftTextExtents8(Dpy, msgfont, reinterpret_cast<const XftChar8*>(text.c_str()),
  172. text.length(), &extents);
  173. cfgX = cfg->getOption("msg_x");
  174. cfgY = cfg->getOption("msg_y");
  175. int shadowXOffset =
  176. Cfg::string2int(cfg->getOption("msg_shadow_xoffset").c_str());
  177. int shadowYOffset =
  178. Cfg::string2int(cfg->getOption("msg_shadow_yoffset").c_str());
  179. int msg_x = Cfg::absolutepos(cfgX, XWidthOfScreen(ScreenOfDisplay(Dpy, Scr)), extents.width);
  180. int msg_y = Cfg::absolutepos(cfgY, XHeightOfScreen(ScreenOfDisplay(Dpy, Scr)), extents.height);
  181. SlimDrawString8 (draw, &msgcolor, msgfont, msg_x, msg_y,
  182. text,
  183. &msgshadowcolor,
  184. shadowXOffset, shadowYOffset);
  185. XFlush(Dpy);
  186. XftDrawDestroy(draw);
  187. }
  188. void Panel::Error(const string& text) {
  189. ClosePanel();
  190. Message(text);
  191. sleep(ERROR_DURATION);
  192. OpenPanel();
  193. ClearPanel();
  194. }
  195. unsigned long Panel::GetColor(const char* colorname) {
  196. XColor color;
  197. XWindowAttributes attributes;
  198. XGetWindowAttributes(Dpy, Root, &attributes);
  199. color.pixel = 0;
  200. if(!XParseColor(Dpy, attributes.colormap, colorname, &color))
  201. cerr << APPNAME << ": can't parse color " << colorname << endl;
  202. else if(!XAllocColor(Dpy, attributes.colormap, &color))
  203. cerr << APPNAME << ": can't allocate color " << colorname << endl;
  204. return color.pixel;
  205. }
  206. void Panel::Cursor(int visible) {
  207. const char* text;
  208. int xx, yy, y2, cheight;
  209. char* txth = "Wj"; // used to get cursor height
  210. switch(field) {
  211. case Get_Passwd:
  212. text = HiddenPasswdBuffer.c_str();
  213. xx = input_pass_x;
  214. yy = input_pass_y;
  215. break;
  216. case Get_Name:
  217. text = NameBuffer.c_str();
  218. xx = input_name_x;
  219. yy = input_name_y;
  220. break;
  221. }
  222. XGlyphInfo extents;
  223. XftTextExtents8(Dpy, font, (XftChar8*)txth, strlen(txth), &extents);
  224. cheight = extents.height;
  225. y2 = yy - extents.y + extents.height;
  226. XftTextExtents8(Dpy, font, (XftChar8*)text, strlen(text), &extents);
  227. xx += extents.width;
  228. if(visible == SHOW) {
  229. XSetForeground(Dpy, TextGC,
  230. GetColor(cfg->getOption("input_color").c_str()));
  231. XDrawLine(Dpy, Win, TextGC,
  232. xx+1, yy-cheight,
  233. xx+1, y2);
  234. } else {
  235. XClearArea(Dpy, Win, xx+1, yy-cheight,
  236. 1, y2-(yy-cheight)+1, false);
  237. }
  238. }
  239. void Panel::EventHandler(const Panel::FieldType& curfield) {
  240. XEvent event;
  241. field=curfield;
  242. bool loop = true;
  243. OnExpose();
  244. while(loop) {
  245. XNextEvent(Dpy, &event);
  246. switch(event.type) {
  247. case Expose:
  248. OnExpose();
  249. break;
  250. case KeyPress:
  251. loop=OnKeyPress(event);
  252. break;
  253. }
  254. }
  255. return;
  256. }
  257. void Panel::OnExpose(void) {
  258. XftDraw *draw = XftDrawCreate(Dpy, Win,
  259. DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
  260. XClearWindow(Dpy, Win);
  261. if (input_pass_x != input_name_x || input_pass_y != input_name_y){
  262. SlimDrawString8 (draw, &inputcolor, font, input_name_x, input_name_y,
  263. NameBuffer,
  264. &inputshadowcolor,
  265. inputShadowXOffset, inputShadowYOffset);
  266. SlimDrawString8 (draw, &inputcolor, font, input_pass_x, input_pass_y,
  267. HiddenPasswdBuffer,
  268. &inputshadowcolor,
  269. inputShadowXOffset, inputShadowYOffset);
  270. } else { //single input mode
  271. switch(field) {
  272. case Get_Passwd:
  273. SlimDrawString8 (draw, &inputcolor, font,
  274. input_pass_x, input_pass_y,
  275. HiddenPasswdBuffer,
  276. &inputshadowcolor,
  277. inputShadowXOffset, inputShadowYOffset);
  278. break;
  279. case Get_Name:
  280. SlimDrawString8 (draw, &inputcolor, font,
  281. input_name_x, input_name_y,
  282. NameBuffer,
  283. &inputshadowcolor,
  284. inputShadowXOffset, inputShadowYOffset);
  285. break;
  286. }
  287. }
  288. XftDrawDestroy (draw);
  289. Cursor(SHOW);
  290. ShowText();
  291. }
  292. bool Panel::OnKeyPress(XEvent& event) {
  293. char ascii;
  294. KeySym keysym;
  295. XComposeStatus compstatus;
  296. int xx;
  297. int yy;
  298. string text;
  299. string formerString = "";
  300. XLookupString(&event.xkey, &ascii, 1, &keysym, &compstatus);
  301. switch(keysym){
  302. case XK_F1:
  303. SwitchSession();
  304. return true;
  305. case XK_F11:
  306. // Take a screenshot
  307. system(cfg->getOption("screenshot_cmd").c_str());
  308. return true;
  309. case XK_Return:
  310. case XK_KP_Enter:
  311. if (field==Get_Name){
  312. // Don't allow an empty username
  313. if (NameBuffer.empty()) return true;
  314. if (NameBuffer==CONSOLE_STR){
  315. action = Console;
  316. } else if (NameBuffer==HALT_STR){
  317. action = Halt;
  318. } else if (NameBuffer==REBOOT_STR){
  319. action = Reboot;
  320. } else if (NameBuffer==SUSPEND_STR){
  321. action = Suspend;
  322. } else if (NameBuffer==EXIT_STR){
  323. action = Exit;
  324. } else{
  325. action = Login;
  326. }
  327. };
  328. return false;
  329. default:
  330. break;
  331. };
  332. Cursor(HIDE);
  333. switch(keysym){
  334. case XK_Delete:
  335. case XK_BackSpace:
  336. switch(field) {
  337. case GET_NAME:
  338. if (! NameBuffer.empty()){
  339. formerString=NameBuffer;
  340. NameBuffer.erase(--NameBuffer.end());
  341. };
  342. break;
  343. case GET_PASSWD:
  344. if (! PasswdBuffer.empty()){
  345. formerString=HiddenPasswdBuffer;
  346. PasswdBuffer.erase(--PasswdBuffer.end());
  347. HiddenPasswdBuffer.erase(--HiddenPasswdBuffer.end());
  348. };
  349. break;
  350. };
  351. break;
  352. case XK_w:
  353. case XK_u:
  354. if (reinterpret_cast<XKeyEvent&>(event).state & ControlMask) {
  355. switch(field) {
  356. case Get_Passwd:
  357. formerString = HiddenPasswdBuffer;
  358. HiddenPasswdBuffer.clear();
  359. PasswdBuffer.clear();
  360. break;
  361. case Get_Name:
  362. formerString = NameBuffer;
  363. NameBuffer.clear();
  364. break;
  365. };
  366. break;
  367. }
  368. // Deliberate fall-through
  369. default:
  370. if (isprint(ascii) && (keysym < XK_Shift_L || keysym > XK_Hyper_R)){
  371. switch(field) {
  372. case GET_NAME:
  373. formerString=NameBuffer;
  374. if (NameBuffer.length() < INPUT_MAXLENGTH_NAME-1){
  375. NameBuffer.append(&ascii,1);
  376. };
  377. break;
  378. case GET_PASSWD:
  379. formerString=HiddenPasswdBuffer;
  380. if (PasswdBuffer.length() < INPUT_MAXLENGTH_NAME-1){
  381. PasswdBuffer.append(&ascii,1);
  382. HiddenPasswdBuffer.append("*");
  383. };
  384. break;
  385. };
  386. };
  387. break;
  388. };
  389. XGlyphInfo extents;
  390. XftDraw *draw = XftDrawCreate(Dpy, Win,
  391. DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
  392. switch(field) {
  393. case Get_Name:
  394. text = NameBuffer;
  395. xx = input_name_x;
  396. yy = input_name_y;
  397. break;
  398. case Get_Passwd:
  399. text = HiddenPasswdBuffer;
  400. xx = input_pass_x;
  401. yy = input_pass_y;
  402. break;
  403. }
  404. if (!formerString.empty()){
  405. char* txth = "Wj"; // get proper maximum height ?
  406. XftTextExtents8(Dpy, font, reinterpret_cast<const XftChar8*>(txth), strlen(txth), &extents);
  407. int maxHeight = extents.height;
  408. XftTextExtents8(Dpy, font, reinterpret_cast<const XftChar8*>(formerString.c_str()),
  409. formerString.length(), &extents);
  410. int maxLength = extents.width;
  411. XClearArea(Dpy, Win, xx-3, yy-maxHeight-3,
  412. maxLength+6, maxHeight+6, false);
  413. }
  414. if (!text.empty()) {
  415. SlimDrawString8 (draw, &inputcolor, font, xx, yy,
  416. text,
  417. &inputshadowcolor,
  418. inputShadowXOffset, inputShadowYOffset);
  419. }
  420. XftDrawDestroy (draw);
  421. Cursor(SHOW);
  422. return true;
  423. }
  424. // Draw welcome and "enter username" message
  425. void Panel::ShowText(){
  426. string cfgX, cfgY;
  427. XGlyphInfo extents;
  428. bool singleInputMode =
  429. input_name_x == input_pass_x &&
  430. input_name_y == input_pass_y;
  431. XftDraw *draw = XftDrawCreate(Dpy, Win,
  432. DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
  433. /* welcome message */
  434. XftTextExtents8(Dpy, welcomefont, (XftChar8*)welcome_message.c_str(),
  435. strlen(welcome_message.c_str()), &extents);
  436. cfgX = cfg->getOption("welcome_x");
  437. cfgY = cfg->getOption("welcome_y");
  438. int shadowXOffset =
  439. Cfg::string2int(cfg->getOption("welcome_shadow_xoffset").c_str());
  440. int shadowYOffset =
  441. Cfg::string2int(cfg->getOption("welcome_shadow_yoffset").c_str());
  442. welcome_x = Cfg::absolutepos(cfgX, image->Width(), extents.width);
  443. welcome_y = Cfg::absolutepos(cfgY, image->Height(), extents.height);
  444. if (welcome_x >= 0 && welcome_y >= 0) {
  445. SlimDrawString8 (draw, &welcomecolor, welcomefont,
  446. welcome_x, welcome_y,
  447. welcome_message,
  448. &welcomeshadowcolor, shadowXOffset, shadowYOffset);
  449. }
  450. /* Enter username-password message */
  451. string msg;
  452. if (!singleInputMode|| field == Get_Passwd ) {
  453. msg = cfg->getOption("password_msg");
  454. XftTextExtents8(Dpy, enterfont, (XftChar8*)msg.c_str(),
  455. strlen(msg.c_str()), &extents);
  456. cfgX = cfg->getOption("password_x");
  457. cfgY = cfg->getOption("password_y");
  458. int shadowXOffset =
  459. Cfg::string2int(cfg->getOption("username_shadow_xoffset").c_str());
  460. int shadowYOffset =
  461. Cfg::string2int(cfg->getOption("username_shadow_yoffset").c_str());
  462. password_x = Cfg::absolutepos(cfgX, image->Width(), extents.width);
  463. password_y = Cfg::absolutepos(cfgY, image->Height(), extents.height);
  464. if (password_x >= 0 && password_y >= 0){
  465. SlimDrawString8 (draw, &entercolor, enterfont, password_x, password_y,
  466. msg, &entershadowcolor, shadowXOffset, shadowYOffset);
  467. }
  468. }
  469. if (!singleInputMode|| field == Get_Name ) {
  470. msg = cfg->getOption("username_msg");
  471. XftTextExtents8(Dpy, enterfont, (XftChar8*)msg.c_str(),
  472. strlen(msg.c_str()), &extents);
  473. cfgX = cfg->getOption("username_x");
  474. cfgY = cfg->getOption("username_y");
  475. int shadowXOffset =
  476. Cfg::string2int(cfg->getOption("username_shadow_xoffset").c_str());
  477. int shadowYOffset =
  478. Cfg::string2int(cfg->getOption("username_shadow_yoffset").c_str());
  479. username_x = Cfg::absolutepos(cfgX, image->Width(), extents.width);
  480. username_y = Cfg::absolutepos(cfgY, image->Height(), extents.height);
  481. if (username_x >= 0 && username_y >= 0){
  482. SlimDrawString8 (draw, &entercolor, enterfont, username_x, username_y,
  483. msg, &entershadowcolor, shadowXOffset, shadowYOffset);
  484. }
  485. }
  486. XftDrawDestroy(draw);
  487. }
  488. string Panel::getSession() {
  489. return session;
  490. }
  491. // choose next available session type
  492. void Panel::SwitchSession() {
  493. session = cfg->nextSession(session);
  494. if (session.size() > 0) {
  495. ShowSession();
  496. }
  497. }
  498. // Display session type on the screen
  499. void Panel::ShowSession() {
  500. XClearWindow(Dpy, Root);
  501. string currsession = "Session: " + session;
  502. XGlyphInfo extents;
  503. XftDraw *draw = XftDrawCreate(Dpy, Root,
  504. DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
  505. XftTextExtents8(Dpy, msgfont, reinterpret_cast<const XftChar8*>(currsession.c_str()),
  506. currsession.length(), &extents);
  507. int msg_x = Cfg::absolutepos("50%", XWidthOfScreen(ScreenOfDisplay(Dpy, Scr)), extents.width);
  508. int msg_y = XHeightOfScreen(ScreenOfDisplay(Dpy, Scr)) - extents.height -100;
  509. int shadowXOffset =
  510. Cfg::string2int(cfg->getOption("msg_shadow_xoffset").c_str());
  511. int shadowYOffset =
  512. Cfg::string2int(cfg->getOption("msg_shadow_yoffset").c_str());
  513. SlimDrawString8(draw, &msgcolor, msgfont, msg_x, msg_y,
  514. currsession,
  515. &msgshadowcolor,
  516. shadowXOffset, shadowYOffset);
  517. XFlush(Dpy);
  518. XftDrawDestroy(draw);
  519. }
  520. void Panel::SlimDrawString8(XftDraw *d, XftColor *color, XftFont *font,
  521. int x, int y, const string& str,
  522. XftColor* shadowColor,
  523. int xOffset, int yOffset)
  524. {
  525. if (xOffset && yOffset) {
  526. XftDrawString8(d, shadowColor, font, x+xOffset, y+yOffset,
  527. reinterpret_cast<const FcChar8*>(str.c_str()), str.length());
  528. }
  529. XftDrawString8(d, color, font, x, y, reinterpret_cast<const FcChar8*>(str.c_str()), str.length());
  530. }
  531. Panel::ActionType Panel::getAction(void) const{
  532. return action;
  533. };
  534. void Panel::Reset(void){
  535. ResetName();
  536. ResetPasswd();
  537. };
  538. void Panel::ResetName(void){
  539. NameBuffer.clear();
  540. };
  541. void Panel::ResetPasswd(void){
  542. PasswdBuffer.clear();
  543. HiddenPasswdBuffer.clear();
  544. };
  545. void Panel::SetName(const string& name){
  546. NameBuffer=name;
  547. return;
  548. };
  549. const string& Panel::GetName(void) const{
  550. return NameBuffer;
  551. };
  552. const string& Panel::GetPasswd(void) const{
  553. return PasswdBuffer;
  554. };