|
@@ -0,0 +1,550 @@
|
|
|
+/* SLiM - Simple Login Manager
|
|
|
+ Copyright (C) 1997, 1998 Per Liden
|
|
|
+ Copyright (C) 2004-05 Simone Rota <sip@varlock.com>
|
|
|
+ Copyright (C) 2004-05 Johannes Winkelmann <jw@tks6.net>
|
|
|
+
|
|
|
+ This program is free software; you can redistribute it and/or modify
|
|
|
+ it under the terms of the GNU General Public License as published by
|
|
|
+ the Free Software Foundation; either version 2 of the License, or
|
|
|
+ (at your option) any later version.
|
|
|
+*/
|
|
|
+
|
|
|
+#include <sstream>
|
|
|
+#include "panel.h"
|
|
|
+
|
|
|
+using namespace std;
|
|
|
+
|
|
|
+Panel::Panel(Display* dpy, int scr, Window root, Cfg* config,
|
|
|
+ const string& themedir) {
|
|
|
+ // Set display
|
|
|
+ Dpy = dpy;
|
|
|
+ Scr = scr;
|
|
|
+ Root = root;
|
|
|
+ cfg = config;
|
|
|
+
|
|
|
+ session = "";
|
|
|
+
|
|
|
+ // Init GC
|
|
|
+ XGCValues gcv;
|
|
|
+ unsigned long gcm;
|
|
|
+ gcm = GCForeground|GCBackground|GCGraphicsExposures;
|
|
|
+ gcv.foreground = GetColor("black");
|
|
|
+ gcv.background = GetColor("white");
|
|
|
+ gcv.graphics_exposures = False;
|
|
|
+ TextGC = XCreateGC(Dpy, Root, gcm, &gcv);
|
|
|
+
|
|
|
+ font = XftFontOpenName(Dpy, Scr, cfg->getOption("input_font").c_str());
|
|
|
+ welcomefont = XftFontOpenName(Dpy, Scr, cfg->getOption("welcome_font").c_str());
|
|
|
+ introfont = XftFontOpenName(Dpy, Scr, cfg->getOption("intro_font").c_str());
|
|
|
+ enterfont = XftFontOpenName(Dpy, Scr, cfg->getOption("username_font").c_str());
|
|
|
+ msgfont = XftFontOpenName(Dpy, Scr, cfg->getOption("msg_font").c_str());
|
|
|
+
|
|
|
+ Visual* visual = DefaultVisual(Dpy, Scr);
|
|
|
+ Colormap colormap = DefaultColormap(Dpy, Scr);
|
|
|
+ // NOTE: using XftColorAllocValue() would be a better solution. Lazy me.
|
|
|
+ XftColorAllocName(Dpy, visual, colormap, cfg->getOption("input_color").c_str(), &inputcolor);
|
|
|
+ XftColorAllocName(Dpy, visual, colormap, cfg->getOption("input_shadow_color").c_str(), &inputshadowcolor);
|
|
|
+ XftColorAllocName(Dpy, visual, colormap, cfg->getOption("welcome_color").c_str(), &welcomecolor);
|
|
|
+ XftColorAllocName(Dpy, visual, colormap, cfg->getOption("welcome_shadow_color").c_str(), &welcomeshadowcolor);
|
|
|
+ XftColorAllocName(Dpy, visual, colormap, cfg->getOption("username_color").c_str(), &entercolor);
|
|
|
+ XftColorAllocName(Dpy, visual, colormap, cfg->getOption("username_shadow_color").c_str(), &entershadowcolor);
|
|
|
+ XftColorAllocName(Dpy, visual, colormap, cfg->getOption("msg_color").c_str(), &msgcolor);
|
|
|
+ XftColorAllocName(Dpy, visual, colormap, cfg->getOption("msg_shadow_color").c_str(), &msgshadowcolor);
|
|
|
+ XftColorAllocName(Dpy, visual, colormap, cfg->getOption("intro_color").c_str(), &introcolor);
|
|
|
+
|
|
|
+ // Load properties from config / theme
|
|
|
+ input_name_x = Cfg::string2int(cfg->getOption("input_name_x").c_str());
|
|
|
+ input_name_y = Cfg::string2int(cfg->getOption("input_name_y").c_str());
|
|
|
+ input_pass_x = Cfg::string2int(cfg->getOption("input_pass_x").c_str());
|
|
|
+ input_pass_y = Cfg::string2int(cfg->getOption("input_pass_y").c_str());
|
|
|
+ inputShadowXOffset =
|
|
|
+ Cfg::string2int(cfg->getOption("input_shadow_xoffset").c_str());
|
|
|
+ inputShadowYOffset =
|
|
|
+ Cfg::string2int(cfg->getOption("input_shadow_yoffset").c_str());
|
|
|
+
|
|
|
+ if (input_pass_x < 0 || input_pass_y < 0){ // single inputbox mode
|
|
|
+ input_pass_x = input_name_x;
|
|
|
+ input_pass_y = input_name_y;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Load panel and background image
|
|
|
+ string panelpng = "";
|
|
|
+ panelpng = panelpng + themedir +"/panel.png";
|
|
|
+ image = new Image;
|
|
|
+ bool loaded = image->Read(panelpng.c_str());
|
|
|
+ if (!loaded) { // try jpeg if png failed
|
|
|
+ panelpng = themedir + "/panel.jpg";
|
|
|
+ loaded = image->Read(panelpng.c_str());
|
|
|
+ if (!loaded) {
|
|
|
+ cerr << APPNAME << ": could not load panel image for theme '"
|
|
|
+ << basename((char*)themedir.c_str()) << "'"
|
|
|
+ << endl;
|
|
|
+ exit(ERR_EXIT);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Image* bg = new Image();
|
|
|
+ string bgstyle = cfg->getOption("background_style");
|
|
|
+ if (bgstyle != "color") {
|
|
|
+ panelpng = themedir +"/background.png";
|
|
|
+ loaded = bg->Read(panelpng.c_str());
|
|
|
+ if (!loaded) { // try jpeg if png failed
|
|
|
+ panelpng = themedir + "/background.jpg";
|
|
|
+ loaded = bg->Read(panelpng.c_str());
|
|
|
+ if (!loaded){
|
|
|
+ cerr << APPNAME << ": could not load background image for theme '"
|
|
|
+ << basename((char*)themedir.c_str()) << "'"
|
|
|
+ << endl;
|
|
|
+ exit(ERR_EXIT);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (bgstyle == "stretch") {
|
|
|
+ bg->Resize(XWidthOfScreen(ScreenOfDisplay(Dpy, Scr)), XHeightOfScreen(ScreenOfDisplay(Dpy, Scr)));
|
|
|
+ } else if (bgstyle == "tile") {
|
|
|
+ bg->Tile(XWidthOfScreen(ScreenOfDisplay(Dpy, Scr)), XHeightOfScreen(ScreenOfDisplay(Dpy, Scr)));
|
|
|
+ } else if (bgstyle == "center") {
|
|
|
+ string hexvalue = cfg->getOption("background_color");
|
|
|
+ hexvalue = hexvalue.substr(1,6);
|
|
|
+ bg->Center(XWidthOfScreen(ScreenOfDisplay(Dpy, Scr)), XHeightOfScreen(ScreenOfDisplay(Dpy, Scr)),
|
|
|
+ hexvalue.c_str());
|
|
|
+ } else { // plain color or error
|
|
|
+ string hexvalue = cfg->getOption("background_color");
|
|
|
+ hexvalue = hexvalue.substr(1,6);
|
|
|
+ bg->Center(XWidthOfScreen(ScreenOfDisplay(Dpy, Scr)), XHeightOfScreen(ScreenOfDisplay(Dpy, Scr)),
|
|
|
+ hexvalue.c_str());
|
|
|
+ }
|
|
|
+
|
|
|
+ string cfgX = cfg->getOption("input_panel_x");
|
|
|
+ string cfgY = cfg->getOption("input_panel_y");
|
|
|
+ X = Cfg::absolutepos(cfgX, XWidthOfScreen(ScreenOfDisplay(Dpy, Scr)), image->Width());
|
|
|
+ Y = Cfg::absolutepos(cfgY, XHeightOfScreen(ScreenOfDisplay(Dpy, Scr)), image->Height());
|
|
|
+
|
|
|
+ // Merge image into background
|
|
|
+ image->Merge(bg, X, Y);
|
|
|
+ PanelPixmap = image->createPixmap(Dpy, Scr, Root);
|
|
|
+
|
|
|
+ // Read (and substitute vars in) the welcome message
|
|
|
+ welcome_message = cfg->getWelcomeMessage();
|
|
|
+ intro_message = cfg->getOption("intro_msg");
|
|
|
+
|
|
|
+ // Init In
|
|
|
+ In = new Input(cfg);
|
|
|
+}
|
|
|
+
|
|
|
+Panel::~Panel() {
|
|
|
+ XftColorFree (Dpy, DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr), &inputcolor);
|
|
|
+ XftColorFree (Dpy, DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr), &msgcolor);
|
|
|
+ XftColorFree (Dpy, DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr), &welcomecolor);
|
|
|
+ XftColorFree (Dpy, DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr), &entercolor);
|
|
|
+ XFreeGC(Dpy, TextGC);
|
|
|
+ delete In;
|
|
|
+ delete image;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+void Panel::OpenPanel() {
|
|
|
+ // Create window
|
|
|
+ Win = XCreateSimpleWindow(Dpy, Root, X, Y,
|
|
|
+ image->Width(),
|
|
|
+ image->Height(),
|
|
|
+ 0, GetColor("white"), GetColor("white"));
|
|
|
+
|
|
|
+ // Events
|
|
|
+ XSelectInput(Dpy, Win, ExposureMask | KeyPressMask);
|
|
|
+
|
|
|
+ // Set background
|
|
|
+ XSetWindowBackgroundPixmap(Dpy, Win, PanelPixmap);
|
|
|
+
|
|
|
+ // Show window
|
|
|
+ XMapWindow(Dpy, Win);
|
|
|
+ XMoveWindow(Dpy, Win, X, Y); // override wm positioning (for tests)
|
|
|
+
|
|
|
+ // Grab keyboard
|
|
|
+ XGrabKeyboard(Dpy, Win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
|
|
|
+
|
|
|
+ XFlush(Dpy);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+void Panel::ClosePanel() {
|
|
|
+ XUngrabKeyboard(Dpy, CurrentTime);
|
|
|
+ XUnmapWindow(Dpy, Win);
|
|
|
+ XDestroyWindow(Dpy, Win);
|
|
|
+ XFlush(Dpy);
|
|
|
+}
|
|
|
+
|
|
|
+void Panel::ClearPanel() {
|
|
|
+ session = "";
|
|
|
+ In->Reset();
|
|
|
+ XClearWindow(Dpy, Root);
|
|
|
+ XClearWindow(Dpy, Win);
|
|
|
+ Cursor(SHOW);
|
|
|
+ ShowText();
|
|
|
+ XFlush(Dpy);
|
|
|
+}
|
|
|
+
|
|
|
+void Panel::Message(const char* text) {
|
|
|
+ string cfgX, cfgY;
|
|
|
+ XGlyphInfo extents;
|
|
|
+ XftDraw *draw = XftDrawCreate(Dpy, Root,
|
|
|
+ DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
|
|
|
+ XftTextExtents8(Dpy, msgfont, (XftChar8*)text,
|
|
|
+ strlen(text), &extents);
|
|
|
+ cfgX = cfg->getOption("msg_x");
|
|
|
+ cfgY = cfg->getOption("msg_y");
|
|
|
+ int shadowXOffset =
|
|
|
+ Cfg::string2int(cfg->getOption("msg_shadow_xoffset").c_str());
|
|
|
+ int shadowYOffset =
|
|
|
+ Cfg::string2int(cfg->getOption("msg_shadow_yoffset").c_str());
|
|
|
+
|
|
|
+ int msg_x = Cfg::absolutepos(cfgX, XWidthOfScreen(ScreenOfDisplay(Dpy, Scr)), extents.width);
|
|
|
+ int msg_y = Cfg::absolutepos(cfgY, XHeightOfScreen(ScreenOfDisplay(Dpy, Scr)), extents.height);
|
|
|
+
|
|
|
+ SlimDrawString8 (draw, &msgcolor, msgfont, msg_x, msg_y,
|
|
|
+ (XftChar8*)text, strlen(text),
|
|
|
+ &msgshadowcolor,
|
|
|
+ shadowXOffset, shadowYOffset);
|
|
|
+ XFlush(Dpy);
|
|
|
+ XftDrawDestroy(draw);
|
|
|
+}
|
|
|
+
|
|
|
+void Panel::Error(const char* text) {
|
|
|
+ ClosePanel();
|
|
|
+ Message(text);
|
|
|
+ sleep(ERROR_DURATION);
|
|
|
+ OpenPanel();
|
|
|
+ ClearPanel();
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+Input* Panel::GetInput() {
|
|
|
+ return In;
|
|
|
+}
|
|
|
+
|
|
|
+unsigned long Panel::GetColor(const char* colorname) {
|
|
|
+ XColor color;
|
|
|
+ XWindowAttributes attributes;
|
|
|
+
|
|
|
+ XGetWindowAttributes(Dpy, Root, &attributes);
|
|
|
+ color.pixel = 0;
|
|
|
+
|
|
|
+ if(!XParseColor(Dpy, attributes.colormap, colorname, &color))
|
|
|
+ cerr << APPNAME << ": can't parse color " << colorname << endl;
|
|
|
+ else if(!XAllocColor(Dpy, attributes.colormap, &color))
|
|
|
+ cerr << APPNAME << ": can't allocate color " << colorname << endl;
|
|
|
+
|
|
|
+ return color.pixel;
|
|
|
+}
|
|
|
+
|
|
|
+void Panel::Cursor(int visible) {
|
|
|
+ char* text;
|
|
|
+ int xx, yy, x2,y2, cheight;
|
|
|
+ char* txth = "Wj"; // used to get cursor height
|
|
|
+
|
|
|
+ switch(In->GetField()) {
|
|
|
+ case GET_PASSWD:
|
|
|
+ text = In->GetHiddenPasswd();
|
|
|
+ xx = input_pass_x;
|
|
|
+ yy = input_pass_y;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case GET_NAME:
|
|
|
+ text = In->GetName();
|
|
|
+ xx = input_name_x;
|
|
|
+ yy = input_name_y;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ XGlyphInfo extents;
|
|
|
+ XftTextExtents8(Dpy, font, (XftChar8*)txth, strlen(txth), &extents);
|
|
|
+ cheight = extents.height;
|
|
|
+ y2 = yy - extents.y + extents.height;
|
|
|
+ XftTextExtents8(Dpy, font, (XftChar8*)text, strlen(text), &extents);
|
|
|
+ xx += extents.width;
|
|
|
+
|
|
|
+ if(visible == SHOW) {
|
|
|
+ XSetForeground(Dpy, TextGC,
|
|
|
+ GetColor(cfg->getOption("input_color").c_str()));
|
|
|
+ XDrawLine(Dpy, Win, TextGC,
|
|
|
+ xx+1, yy-cheight,
|
|
|
+ xx+1, y2);
|
|
|
+ } else {
|
|
|
+ XClearArea(Dpy, Win, xx+1, yy-cheight,
|
|
|
+ 1, y2-(yy-cheight)+1, false);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+int Panel::EventHandler(XEvent* event) {
|
|
|
+ Action = WAIT;
|
|
|
+
|
|
|
+ switch(event->type) {
|
|
|
+ case Expose:
|
|
|
+ OnExpose(event);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case KeyPress:
|
|
|
+ OnKeyPress(event);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return Action;
|
|
|
+}
|
|
|
+
|
|
|
+void Panel::OnExpose(XEvent* event) {
|
|
|
+ char* name = In->GetName();
|
|
|
+ char* passwd = In->GetHiddenPasswd();
|
|
|
+ XftDraw *draw = XftDrawCreate(Dpy, Win,
|
|
|
+ DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
|
|
|
+ if (input_pass_x != input_name_x || input_pass_y != input_name_y){
|
|
|
+ SlimDrawString8 (draw, &inputcolor, font, input_name_x, input_name_y,
|
|
|
+ (XftChar8*)name, strlen(name),
|
|
|
+ &inputshadowcolor,
|
|
|
+ inputShadowXOffset, inputShadowYOffset);
|
|
|
+ SlimDrawString8 (draw, &inputcolor, font, input_pass_x, input_pass_y,
|
|
|
+ (XftChar8*)passwd, strlen(passwd),
|
|
|
+ &inputshadowcolor,
|
|
|
+ inputShadowXOffset, inputShadowYOffset);
|
|
|
+ } else { //single input mode
|
|
|
+ switch(In->GetField()) {
|
|
|
+ case GET_PASSWD:
|
|
|
+ SlimDrawString8 (draw, &inputcolor, font,
|
|
|
+ input_pass_x, input_pass_y,
|
|
|
+ (XftChar8*)passwd, strlen(passwd),
|
|
|
+ &inputshadowcolor,
|
|
|
+ inputShadowXOffset, inputShadowYOffset);
|
|
|
+ break;
|
|
|
+ case GET_NAME:
|
|
|
+ SlimDrawString8 (draw, &inputcolor, font,
|
|
|
+ input_name_x, input_name_y,
|
|
|
+ (XftChar8*)name, strlen(name),
|
|
|
+ &inputshadowcolor,
|
|
|
+ inputShadowXOffset, inputShadowYOffset);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ XftDrawDestroy (draw);
|
|
|
+ Cursor(SHOW);
|
|
|
+ ShowText();
|
|
|
+}
|
|
|
+
|
|
|
+void Panel::OnKeyPress(XEvent* event) {
|
|
|
+ char del;
|
|
|
+ char buffer;
|
|
|
+ KeySym keysym;
|
|
|
+ XComposeStatus compstatus;
|
|
|
+ int xx;
|
|
|
+ int yy;
|
|
|
+ char* text;
|
|
|
+
|
|
|
+ bool singleInputMode =
|
|
|
+ input_name_x == input_pass_x &&
|
|
|
+ input_name_y == input_pass_y;
|
|
|
+ Cursor(HIDE);
|
|
|
+ XLookupString(&event->xkey, &buffer, 1, &keysym, &compstatus);
|
|
|
+ del = In->Key(buffer, keysym, singleInputMode);
|
|
|
+ Action = In->GetAction();
|
|
|
+
|
|
|
+ XGlyphInfo extents, delextents;
|
|
|
+ XftDraw *draw = XftDrawCreate(Dpy, Win,
|
|
|
+ DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
|
|
|
+
|
|
|
+ if (keysym == XK_F1) {
|
|
|
+ SwitchSession();
|
|
|
+ }
|
|
|
+
|
|
|
+ bool clearField = false;
|
|
|
+ string formerString = "";
|
|
|
+ if ((((XKeyEvent*)event)->state & ControlMask)) {
|
|
|
+ if (keysym == XK_w || keysym == XK_u) {
|
|
|
+ clearField = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ switch(In->GetField()) {
|
|
|
+ case GET_PASSWD:
|
|
|
+ if (strlen(In->GetHiddenPasswd()) == 0){
|
|
|
+ // clear name and welcome label if we just entered the
|
|
|
+ // password field
|
|
|
+ if (singleInputMode) {
|
|
|
+ xx = input_name_x;
|
|
|
+ yy = input_name_y;
|
|
|
+ text = In->GetName();
|
|
|
+ XftTextExtents8(Dpy, font, (XftChar8*)text,
|
|
|
+ strlen(text), &extents);
|
|
|
+ XClearWindow(Dpy, Win);
|
|
|
+ ShowText();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (clearField) {
|
|
|
+ formerString = In->GetHiddenPasswd();
|
|
|
+ In->ResetPassword();
|
|
|
+ }
|
|
|
+ text = In->GetHiddenPasswd();
|
|
|
+ xx = input_pass_x;
|
|
|
+ yy = input_pass_y;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case GET_NAME:
|
|
|
+ if (clearField) {
|
|
|
+ formerString = In->GetName();
|
|
|
+ In->ResetName();
|
|
|
+ }
|
|
|
+ text = In->GetName();
|
|
|
+ xx = input_name_x;
|
|
|
+ yy = input_name_y;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ char* txth = "Wj"; // get proper maximum height ?
|
|
|
+ XftTextExtents8(Dpy, font, (XftChar8*)txth, strlen(txth), &extents);
|
|
|
+ int maxHeight = extents.height;
|
|
|
+
|
|
|
+ string tmp = "";
|
|
|
+ if (clearField) {
|
|
|
+ tmp = formerString;
|
|
|
+ } else {
|
|
|
+ tmp = text;
|
|
|
+ tmp = tmp + del;
|
|
|
+ }
|
|
|
+ XftTextExtents8(Dpy, font, (XftChar8*)tmp.c_str(),
|
|
|
+ strlen(tmp.c_str()), &extents);
|
|
|
+ int maxLength = extents.width;
|
|
|
+
|
|
|
+ XClearArea(Dpy, Win, xx-3, yy-maxHeight-3,
|
|
|
+ maxLength+6, maxHeight+6, false);
|
|
|
+
|
|
|
+ if (!clearField) {
|
|
|
+ SlimDrawString8 (draw, &inputcolor, font, xx, yy,
|
|
|
+ (XftChar8*)text, strlen(text),
|
|
|
+ &inputshadowcolor,
|
|
|
+ inputShadowXOffset, inputShadowYOffset);
|
|
|
+ }
|
|
|
+
|
|
|
+ XftDrawDestroy (draw);
|
|
|
+ Cursor(SHOW);
|
|
|
+}
|
|
|
+
|
|
|
+// Draw welcome and "enter username" message
|
|
|
+void Panel::ShowText(){
|
|
|
+ string cfgX, cfgY;
|
|
|
+ int n=-1;
|
|
|
+ XGlyphInfo extents;
|
|
|
+
|
|
|
+ bool singleInputMode =
|
|
|
+ input_name_x == input_pass_x &&
|
|
|
+ input_name_y == input_pass_y;
|
|
|
+
|
|
|
+ XftDraw *draw = XftDrawCreate(Dpy, Win,
|
|
|
+ DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
|
|
|
+ /* welcome message */
|
|
|
+ XftTextExtents8(Dpy, welcomefont, (XftChar8*)welcome_message.c_str(),
|
|
|
+ strlen(welcome_message.c_str()), &extents);
|
|
|
+ cfgX = cfg->getOption("welcome_x");
|
|
|
+ cfgY = cfg->getOption("welcome_y");
|
|
|
+ int shadowXOffset =
|
|
|
+ Cfg::string2int(cfg->getOption("welcome_shadow_xoffset").c_str());
|
|
|
+ int shadowYOffset =
|
|
|
+ Cfg::string2int(cfg->getOption("welcome_shadow_yoffset").c_str());
|
|
|
+ welcome_x = Cfg::absolutepos(cfgX, image->Width(), extents.width);
|
|
|
+ welcome_y = Cfg::absolutepos(cfgY, image->Height(), extents.height);
|
|
|
+ if (welcome_x >= 0 && welcome_y >= 0) {
|
|
|
+ SlimDrawString8 (draw, &welcomecolor, welcomefont,
|
|
|
+ welcome_x, welcome_y,
|
|
|
+ (XftChar8*)welcome_message.c_str(),
|
|
|
+ strlen(welcome_message.c_str()),
|
|
|
+ &welcomeshadowcolor, shadowXOffset, shadowYOffset);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Enter username-password message */
|
|
|
+ string msg;
|
|
|
+ if (!singleInputMode|| In->GetField() == GET_PASSWD ) {
|
|
|
+ msg = cfg->getOption("password_msg");
|
|
|
+ XftTextExtents8(Dpy, enterfont, (XftChar8*)msg.c_str(),
|
|
|
+ strlen(msg.c_str()), &extents);
|
|
|
+ cfgX = cfg->getOption("password_x");
|
|
|
+ cfgY = cfg->getOption("password_y");
|
|
|
+ int shadowXOffset =
|
|
|
+ Cfg::string2int(cfg->getOption("username_shadow_xoffset").c_str());
|
|
|
+ int shadowYOffset =
|
|
|
+ Cfg::string2int(cfg->getOption("username_shadow_yoffset").c_str());
|
|
|
+ password_x = Cfg::absolutepos(cfgX, image->Width(), extents.width);
|
|
|
+ password_y = Cfg::absolutepos(cfgY, image->Height(), extents.height);
|
|
|
+ if (password_x >= 0 && password_y >= 0){
|
|
|
+ SlimDrawString8 (draw, &entercolor, enterfont, password_x, password_y,
|
|
|
+ (XftChar8*)msg.c_str(), strlen(msg.c_str()),
|
|
|
+ &entershadowcolor, shadowXOffset, shadowYOffset);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!singleInputMode|| In->GetField() == GET_NAME ) {
|
|
|
+ msg = cfg->getOption("username_msg");
|
|
|
+ XftTextExtents8(Dpy, enterfont, (XftChar8*)msg.c_str(),
|
|
|
+ strlen(msg.c_str()), &extents);
|
|
|
+ cfgX = cfg->getOption("username_x");
|
|
|
+ cfgY = cfg->getOption("username_y");
|
|
|
+ int shadowXOffset =
|
|
|
+ Cfg::string2int(cfg->getOption("username_shadow_xoffset").c_str());
|
|
|
+ int shadowYOffset =
|
|
|
+ Cfg::string2int(cfg->getOption("username_shadow_yoffset").c_str());
|
|
|
+ username_x = Cfg::absolutepos(cfgX, image->Width(), extents.width);
|
|
|
+ username_y = Cfg::absolutepos(cfgY, image->Height(), extents.height);
|
|
|
+ if (username_x >= 0 && username_y >= 0){
|
|
|
+ SlimDrawString8 (draw, &entercolor, enterfont, username_x, username_y,
|
|
|
+ (XftChar8*)msg.c_str(), strlen(msg.c_str()),
|
|
|
+ &entershadowcolor, shadowXOffset, shadowYOffset);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ XftDrawDestroy(draw);
|
|
|
+}
|
|
|
+
|
|
|
+string Panel::getSession() {
|
|
|
+ return session;
|
|
|
+}
|
|
|
+
|
|
|
+// choose next available session type
|
|
|
+void Panel::SwitchSession() {
|
|
|
+ session = cfg->nextSession(session);
|
|
|
+ //TODO: get sessions from cfg and cycle to the next one
|
|
|
+ ShowSession();
|
|
|
+}
|
|
|
+
|
|
|
+// Display session type on the screen
|
|
|
+void Panel::ShowSession() {
|
|
|
+ XClearWindow(Dpy, Root);
|
|
|
+ string currsession = "Session: " + session;
|
|
|
+ char* text = (char*) currsession.c_str();
|
|
|
+ XGlyphInfo extents;
|
|
|
+ XftDraw *draw = XftDrawCreate(Dpy, Root,
|
|
|
+ DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
|
|
|
+ XftTextExtents8(Dpy, msgfont, (XftChar8*)text,
|
|
|
+ strlen(text), &extents);
|
|
|
+ int msg_x = Cfg::absolutepos("50%", XWidthOfScreen(ScreenOfDisplay(Dpy, Scr)), extents.width);
|
|
|
+ int msg_y = XHeightOfScreen(ScreenOfDisplay(Dpy, Scr)) - extents.height -100;
|
|
|
+ int shadowXOffset =
|
|
|
+ Cfg::string2int(cfg->getOption("welcome_shadow_xoffset").c_str());
|
|
|
+ int shadowYOffset =
|
|
|
+ Cfg::string2int(cfg->getOption("welcome_shadow_yoffset").c_str());
|
|
|
+
|
|
|
+ SlimDrawString8(draw, &msgcolor, msgfont, msg_x, msg_y,
|
|
|
+ (XftChar8*)text, strlen(text),
|
|
|
+ &msgshadowcolor,
|
|
|
+ shadowXOffset, shadowYOffset);
|
|
|
+ XFlush(Dpy);
|
|
|
+ XftDrawDestroy(draw);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void Panel::SlimDrawString8(XftDraw *d, XftColor *color, XftFont *font,
|
|
|
+ int x, int y, XftChar8 *string, int len,
|
|
|
+ XftColor* shadowColor,
|
|
|
+ int xOffset, int yOffset)
|
|
|
+{
|
|
|
+ if (xOffset && yOffset) {
|
|
|
+ XftDrawString8(d, shadowColor, font, x+xOffset, y+yOffset,
|
|
|
+ string, len);
|
|
|
+ }
|
|
|
+ XftDrawString8(d, color, font, x, y, string, len);
|
|
|
+}
|