panel.cpp 23 KB

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