panel.cpp 22 KB

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