New structure of auto-type classes
Use xvkbd code for sending auto-type keys Fixed bug that prevented auto-typing non-latin1 chars Added Italian translation Fixed some new gcc warnings git-svn-id: https://svn.code.sf.net/p/keepassx/code/trunk@238 b624d157-de02-0410-bad0-e51aec6abb33
This commit is contained in:
parent
bb80c9616a
commit
888d0982d4
|
@ -25,4 +25,4 @@ SUBDIRS += src
|
|||
message("Install Prefix:" $$PREFIX)
|
||||
#message("KDE Prefix:" $$KDEDIR)
|
||||
message("*** Makefile successfully generated.")
|
||||
message("*** Start make now.")
|
||||
message("*** Start make now.")
|
||||
|
|
|
@ -28,9 +28,12 @@ KeepassApplication::KeepassApplication(int& argc, char** argv) : QApplication(ar
|
|||
}
|
||||
|
||||
bool KeepassApplication::x11EventFilter(XEvent* event){
|
||||
if (event->type==KeyPress && AutoType::shortcut.key!=0u && event->xkey.keycode==XKeysymToKeycode(event->xkey.display,HelperX11::getKeysym(AutoType::shortcut.key)) && (event->xkey.state&remove_invalid)==HelperX11::getShortcutModifierMask(AutoType::shortcut) && focusWidget()==NULL ){
|
||||
if (event->type==KeyPress && autoType->getShortcut().key!=0u &&
|
||||
event->xkey.keycode==XKeysymToKeycode(event->xkey.display,HelperX11::getKeysym(autoType->getShortcut().key)) &&
|
||||
(event->xkey.state&remove_invalid)==HelperX11::getShortcutModifierMask(autoType->getShortcut()) && focusWidget()==NULL )
|
||||
{
|
||||
EventOccurred = true;
|
||||
AutoType::performGlobal();
|
||||
autoType->performGlobal();
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
extern const QDateTime Date_Never;
|
||||
|
||||
typedef enum CryptAlgorithm{
|
||||
enum CryptAlgorithm{
|
||||
Rijndael_Cipher=0,
|
||||
Twofish_Cipher=1
|
||||
};
|
||||
|
@ -371,7 +371,7 @@ public:
|
|||
*/
|
||||
virtual QPixmap& icon(int index)=0;
|
||||
//! \return the number of icons provided by the database. This number can vary at runtime if the database supports custom icons.
|
||||
virtual int numIcons()=0;
|
||||
virtual int numIcons()=0;
|
||||
|
||||
/*! Deletes all old invalid handles of the database.
|
||||
Make sure that there are no pointers to those handles which are still in use before calling this function.*/
|
||||
|
@ -395,16 +395,8 @@ public:
|
|||
\param Fields A pointer to a six element bool array. It defines which fields are included into the search. The order is: title, username, url, password, comment, attachment description. The pointer can also be NULL, than the default pattern is used instead.
|
||||
\return the search results as a list of pointers to the entry handles.*/
|
||||
virtual QList<IEntryHandle*> search(IGroupHandle* Group,const QString& SearchString, bool CaseSensitve, bool RegExp,bool Recursive,bool* Fields)=0;
|
||||
|
||||
//! Moves an entry to the recycle bin.
|
||||
virtual void moveToTrash(IEntryHandle* entry)=0;
|
||||
|
||||
//! \returns all entries of the recycle bin.
|
||||
virtual QList<IEntryHandle*> trashEntries()=0;
|
||||
|
||||
//! Empty the recycle bin.
|
||||
virtual void emptyTrash()=0;
|
||||
|
||||
|
||||
//virtual IDatabase* groupToNewDb(IGroupHandle* group)=0;
|
||||
};
|
||||
|
||||
class IKdbSettings{
|
||||
|
|
|
@ -247,10 +247,16 @@ void Kdb3Database::parseCustomIconsMetaStreamV3(const QByteArray& dta){
|
|||
}
|
||||
|
||||
void Kdb3Database::parseGroupTreeStateMetaStream(const QByteArray& dta){
|
||||
if(dta.size()<4){qWarning("Discarded metastream KPX_GROUP_TREE_STATE because of a parsing error."); return;}
|
||||
if(dta.size()<4){
|
||||
qWarning("Discarded metastream KPX_GROUP_TREE_STATE because of a parsing error.");
|
||||
return;
|
||||
}
|
||||
quint32 Num;
|
||||
memcpyFromLEnd32(&Num,dta.data());
|
||||
if(Num*5!=dta.size()-4){qWarning("Discarded metastream KPX_GROUP_TREE_STATE because of a parsing error."); return;}
|
||||
if(Num*5!=dta.size()-4){
|
||||
qWarning("Discarded metastream KPX_GROUP_TREE_STATE because of a parsing error.");
|
||||
return;
|
||||
}
|
||||
TreeStateMetaStream.clear();
|
||||
for(int i=0;i<Num;i++){
|
||||
quint32 GroupID;
|
||||
|
@ -1002,14 +1008,17 @@ QList<IGroupHandle*> Kdb3Database::groups(){
|
|||
quint32 Kdb3Database::getNewGroupId(){
|
||||
quint32 id;
|
||||
bool used;
|
||||
while(1){
|
||||
do{
|
||||
used=false;
|
||||
randomize(&id,4);
|
||||
if(!id)continue; //group IDs must not be 0
|
||||
for(int j=0;j<Groups.size();j++){
|
||||
if(Groups[j].Id==id)used=true;}
|
||||
if(used==false)break;
|
||||
}
|
||||
if(Groups[j].Id==id){
|
||||
used=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(used);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
@ -1027,6 +1036,10 @@ IGroupHandle* Kdb3Database::addGroup(const CGroup* group,IGroupHandle* ParentHan
|
|||
else{
|
||||
Groups.back().Parent=&RootGroup;
|
||||
Groups.back().Index=RootGroup.Children.size();
|
||||
if (group->Title!="Backup" && RootGroup.Children.size() && RootGroup.Children.last()->Title=="Backup"){
|
||||
RootGroup.Children.last()->Index = Groups.back().Index;
|
||||
Groups.back().Index--;
|
||||
}
|
||||
Groups.back().Parent->Children.append(&Groups.back());
|
||||
}
|
||||
return &GroupHandles.back();
|
||||
|
@ -1256,7 +1269,7 @@ bool Kdb3Database::save(){
|
|||
}
|
||||
if(!File->isOpen()){
|
||||
if(!File->open(QIODevice::ReadWrite)){
|
||||
error= tr("Could not open file for writing.");
|
||||
error = tr("Could not open file for writing.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1376,14 +1389,16 @@ bool Kdb3Database::save(){
|
|||
delete [] buffer;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!File->resize(EncryptedPartSize+DB_HEADER_SIZE)){
|
||||
|
||||
int size = EncryptedPartSize+DB_HEADER_SIZE;
|
||||
|
||||
if(!File->resize(size)){
|
||||
delete [] buffer;
|
||||
error=decodeFileError(File->error());
|
||||
return false;
|
||||
}
|
||||
File->seek(0);
|
||||
if(File->write(buffer,EncryptedPartSize+DB_HEADER_SIZE)!=EncryptedPartSize+DB_HEADER_SIZE){
|
||||
if(File->write(buffer,size)!=size){
|
||||
delete [] buffer;
|
||||
error=decodeFileError(File->error());
|
||||
return false;
|
||||
|
@ -1824,34 +1839,6 @@ bool Kdb3Database::changeFile(const QString& filename){
|
|||
return true;
|
||||
}
|
||||
|
||||
void Kdb3Database::moveToTrash(IEntryHandle* entry){
|
||||
TrashEntry trash=*((TrashEntry*)dynamic_cast<EntryHandle*>(entry)->Entry);
|
||||
IGroupHandle* CurGroup=entry->group();
|
||||
while(CurGroup){
|
||||
trash.GroupPath << CurGroup->title();
|
||||
CurGroup=CurGroup->parent();
|
||||
}
|
||||
deleteEntry(entry);
|
||||
trash.Group=NULL;
|
||||
TrashEntries.append(trash);
|
||||
TrashHandles.append(EntryHandle(this));
|
||||
TrashHandles.back().Entry=&TrashEntries.back();
|
||||
TrashEntries.back().Handle=&TrashHandles.back();
|
||||
}
|
||||
|
||||
void Kdb3Database::emptyTrash(){
|
||||
TrashEntries.clear();
|
||||
TrashHandles.clear();
|
||||
}
|
||||
|
||||
QList<IEntryHandle*> Kdb3Database::trashEntries(){
|
||||
QList<IEntryHandle*> handles;
|
||||
for(int i=0; i<TrashHandles.size();i++)
|
||||
if(TrashHandles[i].isValid())
|
||||
handles << &TrashHandles[i];
|
||||
return handles;
|
||||
}
|
||||
|
||||
void Kdb3Database::generateMasterKey(){
|
||||
randomize(TransfRandomSeed,32);
|
||||
RawMasterKey.unlock();
|
||||
|
@ -1861,6 +1848,34 @@ void Kdb3Database::generateMasterKey(){
|
|||
MasterKey.lock();
|
||||
}
|
||||
|
||||
/*void Kdb3Database::copyTree(Kdb3Database* db, GroupHandle* orgGroup, IGroupHandle* parent) {
|
||||
IGroupHandle* newParent = db->addGroup(orgGroup->Group, parent);
|
||||
|
||||
QList<IEntryHandle*> entryList = entries(orgGroup);
|
||||
for (int i=0; i<entryList.size(); i++) {
|
||||
EntryHandle* entry = static_cast<EntryHandle*>(entryList[i]);
|
||||
db->addEntry(entry->Entry, newParent);
|
||||
}
|
||||
|
||||
QList<IGroupHandle*> children = orgGroup->children();
|
||||
for (int i=0; i<children.size(); i++) {
|
||||
GroupHandle* child = static_cast<GroupHandle*>(children[i]);
|
||||
copyTree(db, child, newParent);
|
||||
}
|
||||
}
|
||||
|
||||
IDatabase* Kdb3Database::groupToNewDb(IGroupHandle* group){
|
||||
Kdb3Database* db = new Kdb3Database();
|
||||
db->create();
|
||||
copyTree(db, static_cast<GroupHandle*>(group), NULL);
|
||||
|
||||
db->changeFile("/ramtmp/test.kdb");
|
||||
if (!db->save())
|
||||
qWarning("%s", CSTR(db->error));
|
||||
|
||||
return db;
|
||||
}*/
|
||||
|
||||
|
||||
void KeyTransform::transform(quint8* src, quint8* dst, quint8* KeySeed, int rounds){
|
||||
KeyTransform* ktLeft = new KeyTransform(&src[0], &dst[0], KeySeed, rounds);
|
||||
|
@ -1896,9 +1911,8 @@ int KeyTransformBenchmark::benchmark(int pMSecs){
|
|||
KeyTransformBenchmark* ktbRight = new KeyTransformBenchmark(pMSecs);
|
||||
ktbLeft->start();
|
||||
ktbRight->start();
|
||||
while (ktbLeft->isRunning() || ktbRight->isRunning()){
|
||||
QThread::msleep(100);
|
||||
}
|
||||
ktbLeft->wait();
|
||||
ktbRight->wait();
|
||||
int num = ktbLeft->rounds + ktbRight->rounds;
|
||||
delete ktbLeft;
|
||||
delete ktbRight;
|
||||
|
|
|
@ -133,11 +133,6 @@ public:
|
|||
QList<StdEntry*> Entries;
|
||||
};
|
||||
|
||||
class TrashEntry: public StdEntry{
|
||||
public:
|
||||
QStringList GroupPath;
|
||||
};
|
||||
|
||||
Kdb3Database();
|
||||
virtual ~Kdb3Database(){};
|
||||
virtual bool load(QString identifier);
|
||||
|
@ -150,7 +145,7 @@ public:
|
|||
virtual bool isKeyError();
|
||||
virtual void cleanUpHandles();
|
||||
virtual QPixmap& icon(int index);
|
||||
virtual int numIcons();
|
||||
virtual int numIcons();
|
||||
virtual void addIcon(const QPixmap& icon);
|
||||
virtual void removeIcon(int index);
|
||||
virtual void replaceIcon(int index,const QPixmap& icon);
|
||||
|
@ -178,9 +173,6 @@ public:
|
|||
virtual IEntryHandle* addEntry(const CEntry* NewEntry, IGroupHandle* group);
|
||||
virtual void moveEntry(IEntryHandle* entry, IGroupHandle* group);
|
||||
virtual void deleteLastEntry();
|
||||
virtual void moveToTrash(IEntryHandle* entry);
|
||||
virtual QList<IEntryHandle*> trashEntries();
|
||||
virtual void emptyTrash();
|
||||
|
||||
|
||||
virtual QList<IGroupHandle*> groups();
|
||||
|
@ -192,8 +184,7 @@ public:
|
|||
virtual bool isParent(IGroupHandle* parent, IGroupHandle* child);
|
||||
|
||||
virtual void generateMasterKey();
|
||||
|
||||
|
||||
//virtual IDatabase* groupToNewDb(IGroupHandle* group);
|
||||
|
||||
private:
|
||||
QDateTime dateFromPackedStruct5(const unsigned char* pBytes);
|
||||
|
@ -220,6 +211,7 @@ private:
|
|||
void getEntriesRecursive(IGroupHandle* Group, QList<IEntryHandle*>& EntryList);
|
||||
void rebuildIndices(QList<StdGroup*>& list);
|
||||
void restoreGroupTreeState();
|
||||
//void copyTree(Kdb3Database* db, GroupHandle* orgGroup, IGroupHandle* parent);
|
||||
|
||||
StdEntry* getEntry(const KpxUuid& uuid);
|
||||
StdEntry* getEntry(EntryHandle* handle);
|
||||
|
@ -231,10 +223,8 @@ private:
|
|||
|
||||
QList<EntryHandle> EntryHandles;
|
||||
QList<GroupHandle> GroupHandles;
|
||||
QList<EntryHandle> TrashHandles;
|
||||
QList<StdEntry> Entries;
|
||||
QList<StdGroup> Groups;
|
||||
QList<TrashEntry> TrashEntries;
|
||||
StdGroup RootGroup;
|
||||
QList<QPixmap>CustomIcons;
|
||||
QFile* File;
|
||||
|
|
|
@ -365,7 +365,7 @@
|
|||
* This default definition of SWAP works, but on many platforms there is a
|
||||
* more efficient implementation.
|
||||
*/
|
||||
#define BSWAP(x) (ROL32((x),8)&0x00ff00ff | ROR32((x),8) & 0xff00ff00)
|
||||
#define BSWAP(x) ( (ROL32((x),8) & 0x00ff00ff) | (ROR32((x),8) & 0xff00ff00) )
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -92,7 +92,7 @@ void AutoTypeDlg::resizeEvent(QResizeEvent* event){
|
|||
bool AutoTypeDlg::event(QEvent* event){
|
||||
if (!EventOccurred){
|
||||
int t = event->type();
|
||||
if ( t>=QEvent::MouseButtonPress&&t<=QEvent::KeyRelease || t>=QEvent::HoverEnter&&t<=QEvent::HoverMove )
|
||||
if ( (t>=QEvent::MouseButtonPress && t<=QEvent::KeyRelease) || (t>=QEvent::HoverEnter && t<=QEvent::HoverMove) )
|
||||
EventOccurred = true;
|
||||
}
|
||||
return QWidget::event(event);
|
||||
|
@ -100,6 +100,5 @@ bool AutoTypeDlg::event(QEvent* event){
|
|||
|
||||
void AutoTypeDlg::itemSelected(QTreeWidgetItem* item){
|
||||
close();
|
||||
QString err;
|
||||
AutoType::perform(itemToEntry[item].dbHandle, err, pWasLocked, itemToEntry[item].nr, pWasLocked);
|
||||
autoType->perform(itemToEntry[item].dbHandle, pWasLocked, itemToEntry[item].nr, pWasLocked);
|
||||
}
|
||||
|
|
|
@ -60,8 +60,9 @@ void CSelectIconDlg::OnAddIcon(){
|
|||
QPixmap icon;
|
||||
if(!icon.load(filenames[i])){
|
||||
errors+=tr("%1: File could not be loaded.").arg(filenames[i].section("/",-1)).append("\n");
|
||||
continue;}
|
||||
dynamic_cast<ICustomIcons*>(db)->addIcon(icon.scaled(16,16,Qt::KeepAspectRatio,Qt::SmoothTransformation));
|
||||
continue;
|
||||
}
|
||||
dynamic_cast<ICustomIcons*>(db)->addIcon(icon.scaled(16,16,Qt::KeepAspectRatio,Qt::SmoothTransformation));
|
||||
}
|
||||
if(errors.size())
|
||||
QMessageBox::warning(this,tr("Error"),tr("An error occured while loading the icon(s):").append("\n").append(errors));
|
||||
|
|
|
@ -72,7 +72,7 @@ CSettingsDlg::CSettingsDlg(QWidget* parent):QDialog(parent,Qt::Dialog)
|
|||
#endif
|
||||
|
||||
#ifdef GLOBAL_AUTOTYPE
|
||||
pShortcut = AutoType::shortcut;
|
||||
pShortcut = autoType->getShortcut();
|
||||
connect(this,SIGNAL(rejected()),SLOT(resetGlobalShortcut()));
|
||||
#endif
|
||||
|
||||
|
@ -417,7 +417,7 @@ void CSettingsDlg::OnSelectLanguage(int index){
|
|||
|
||||
#ifdef GLOBAL_AUTOTYPE
|
||||
void CSettingsDlg::resetGlobalShortcut(){
|
||||
AutoType::unregisterGlobalShortcut();
|
||||
AutoType::registerGlobalShortcut(pShortcut);
|
||||
autoType->unregisterGlobalShortcut();
|
||||
autoType->registerGlobalShortcut(pShortcut);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
TargetWindowDlg::TargetWindowDlg(QWidget* parent) : QDialog(parent){
|
||||
setupUi(this);
|
||||
QStringList windowTitles = AutoType::getAllWindowTitles();
|
||||
QStringList windowTitles = autoType->getAllWindowTitles();
|
||||
windowTitles.sort();
|
||||
for (QStringList::const_iterator i = windowTitles.constBegin(); i != windowTitles.constEnd(); ++i)
|
||||
comboWindow->addItem(*i);
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "dialogs/SimplePasswordDlg.h"
|
||||
|
||||
QFile* ExporterBase::openFile(QWidget* parent, QString id, QStringList Filters){
|
||||
QString filename=KpxFileDialogs::saveFile(parent,id,tr("Import File..."),Filters);
|
||||
QString filename=KpxFileDialogs::saveFile(parent,id,tr("Export File..."),Filters);
|
||||
if(filename.isEmpty())return NULL;
|
||||
QFile* file=new QFile(filename);
|
||||
if(!file->open(QIODevice::ReadWrite|QIODevice::Truncate)){
|
||||
|
|
|
@ -34,7 +34,7 @@ bool Import_KWalletXml::importDatabase(QWidget* GuiParent, IDatabase* db){
|
|||
int col,line;
|
||||
if(!doc.setContent(QString::fromUtf8((char*)buffer,len),false,&xmlerr,&line,&col)){
|
||||
qWarning("Import_PwManager::parseXmlContent():\n");
|
||||
qWarning(((xmlerr+" (Line:%1 Column:%2)").arg(line).arg(col)+QString('\n')).toAscii());
|
||||
qWarning("%s (Line:%d Column:%d)\n",CSTR(xmlerr), line, col);
|
||||
QMessageBox::critical(GuiParent,tr("Import Failed"),tr("Invalid XML data (see stdout for details)."));
|
||||
delete [] buffer;
|
||||
return false;}
|
||||
|
|
|
@ -45,7 +45,7 @@ bool Import_KeePassX_Xml::importDatabase(QWidget* Parent, IDatabase* database){
|
|||
QStringList GroupNames;
|
||||
for(int i=0;i<TopLevelGroupNodes.count();i++){
|
||||
if(TopLevelGroupNodes.at(i).toElement().tagName()!="group"){
|
||||
qWarning("Import_KeePassX_Xml: Error: Unknow tag '%s'",TopLevelGroupNodes.at(i).toElement().tagName().toUtf8().constData());
|
||||
qWarning("Import_KeePassX_Xml: Error: Unknow tag '%s'",CSTR(TopLevelGroupNodes.at(i).toElement().tagName()));
|
||||
QMessageBox::critical(GuiParent,tr("Import Failed"),tr("Parsing error: File is no valid KeePassX XML file."));
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -116,8 +116,9 @@ bool Import_PwManager::parseXmlContent(char* content){
|
|||
int col,line;
|
||||
if(!db.setContent(QString::fromUtf8(content,strlen(content)-1),false,&err,&line,&col)){
|
||||
qWarning("Import_PwManager::parseXmlContent():\n");
|
||||
qWarning(((err+" (Line:%1 Column:%2)").arg(line).arg(col)+QString('\n')).toAscii());
|
||||
return false;}
|
||||
qWarning("%s (Line:%d Column:%d)\n", CSTR(err), line, col);
|
||||
return false;
|
||||
}
|
||||
QDomElement root=db.documentElement();
|
||||
if(root.tagName()!="P")return false;
|
||||
//Achtung! Kommentare und Kategorien haben das selbe Tag "c"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005-2006 by Tarek Saidi, Felix Geyer *
|
||||
* Copyright (C) 2005-2008 by Tarek Saidi, Felix Geyer *
|
||||
* tarek.saidi@arcor.de *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
@ -16,34 +16,42 @@
|
|||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _AUTOTYPE_H_
|
||||
#define _AUTOTYPE_H_
|
||||
|
||||
class KeepassMainWindow;
|
||||
void initAutoType(KeepassMainWindow* mainWin);
|
||||
|
||||
class AutoType{
|
||||
public:
|
||||
virtual void perform(IEntryHandle* entry, bool hideWindow=true, int nr=0, bool wasLocked=false) = 0;
|
||||
};
|
||||
|
||||
#ifdef GLOBAL_AUTOTYPE
|
||||
struct Shortcut{
|
||||
bool ctrl, shift, alt, altgr, win;
|
||||
quint32 key;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef AUTOTYPE
|
||||
class KeepassMainWindow;
|
||||
|
||||
class AutoType{
|
||||
class AutoTypeGlobal : public AutoType{
|
||||
public:
|
||||
static KeepassMainWindow* MainWin;
|
||||
static void perform(IEntryHandle* entry, QString& err,bool hideWindow=true,int nr=0,bool wasLocked=false);
|
||||
#ifdef GLOBAL_AUTOTYPE
|
||||
static Shortcut shortcut;
|
||||
static void performGlobal();
|
||||
static bool registerGlobalShortcut(const Shortcut& s);
|
||||
static void unregisterGlobalShortcut();
|
||||
static void init();
|
||||
static QStringList getAllWindowTitles();
|
||||
#endif // GLOBAL_AUTOTYPE
|
||||
virtual void performGlobal() = 0;
|
||||
inline const Shortcut& getShortcut() { return shortcut; };
|
||||
virtual bool registerGlobalShortcut(const Shortcut& s) = 0;
|
||||
virtual void unregisterGlobalShortcut() = 0;
|
||||
virtual QStringList getAllWindowTitles() = 0;
|
||||
|
||||
protected:
|
||||
Shortcut shortcut;
|
||||
};
|
||||
#endif // AUTOTYPE
|
||||
#endif
|
||||
|
||||
#ifdef GLOBAL_AUTOTYPE
|
||||
extern AutoTypeGlobal* autoType;
|
||||
#else
|
||||
extern AutoType* autoType;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,267 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005-2008 by Tarek Saidi, Felix Geyer *
|
||||
* tarek.saidi@arcor.de *
|
||||
* *
|
||||
* 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; version 2 of the License. *
|
||||
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "AutoTypeGlobalX11.h"
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "lib/HelperX11.h"
|
||||
#include "dialogs/AutoTypeDlg.h"
|
||||
#include <QX11Info>
|
||||
|
||||
AutoTypeGlobal* autoType = NULL;
|
||||
|
||||
void initAutoType(KeepassMainWindow* mainWin) {
|
||||
autoType = new AutoTypeGlobalX11(mainWin);
|
||||
}
|
||||
|
||||
AutoTypeGlobalX11::AutoTypeGlobalX11(KeepassMainWindow* mainWin) : AutoTypeX11(mainWin) {
|
||||
wm_state = XInternAtom(dpy, "WM_STATE", true);
|
||||
windowRoot = XRootWindow(dpy, mainWin->x11Info().screen());
|
||||
focusedWindow = NULL;
|
||||
//windowBlacklist << "kicker" << "KDE Desktop";
|
||||
classBlacklist << "desktop_window" << "gnome-panel"; // Gnome
|
||||
classBlacklist << "kdesktop" << "kicker"; // KDE 3
|
||||
classBlacklist << "xfdesktop" << "xfce4-panel"; // Xfce 4
|
||||
}
|
||||
|
||||
void AutoTypeGlobalX11::perform(IEntryHandle* entry, bool hideWindow, int nr, bool wasLocked){
|
||||
if (focusedWindow && (!hideWindow || wasLocked)) { // detect if global auto-type
|
||||
XSetInputFocus(dpy, focusedWindow, RevertToPointerRoot, CurrentTime);
|
||||
focusedWindow = NULL;
|
||||
}
|
||||
AutoTypeX11::perform(entry, hideWindow, nr, wasLocked);
|
||||
}
|
||||
|
||||
void AutoTypeGlobalX11::windowTitles(Window window, QStringList& titleList){
|
||||
Atom type = None;
|
||||
int format;
|
||||
unsigned long nitems, after;
|
||||
unsigned char* data;
|
||||
XGetWindowProperty(dpy, window, wm_state, 0, 0, false, AnyPropertyType, &type, &format, &nitems, &after, &data);
|
||||
if (type){
|
||||
XTextProperty textProp;
|
||||
if (XGetWMName(dpy, window, &textProp) != 0) {
|
||||
char** list = NULL;
|
||||
int count;
|
||||
if (Xutf8TextPropertyToTextList(dpy, &textProp, &list, &count)>=0 && list){
|
||||
QString title = QString::fromUtf8(list[0]);
|
||||
|
||||
QString className;
|
||||
XClassHint* wmClass = XAllocClassHint();
|
||||
if (XGetClassHint(dpy, window, wmClass)!=0 && wmClass->res_name!=NULL)
|
||||
className = QString::fromLocal8Bit(wmClass->res_name);
|
||||
XFree(wmClass);
|
||||
|
||||
if (window!=windowRoot && window!=mainWin->winId() &&
|
||||
(QApplication::activeWindow()==NULL || window!=QApplication::activeWindow()->winId()) &&
|
||||
// !windowBlacklist.contains(title) &&
|
||||
(className.isNull() || !classBlacklist.contains(className))
|
||||
){
|
||||
titleList.append(title);
|
||||
}
|
||||
XFreeStringList(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Window root;
|
||||
Window parent;
|
||||
Window* children = NULL;
|
||||
unsigned int num_children;
|
||||
int tree = XQueryTree(dpy, window, &root, &parent, &children, &num_children);
|
||||
if (tree && children){
|
||||
for (int i=0; i<num_children; i++)
|
||||
windowTitles(children[i], titleList);
|
||||
}
|
||||
else
|
||||
XFree(children);
|
||||
}
|
||||
|
||||
QStringList AutoTypeGlobalX11::getAllWindowTitles(){
|
||||
QStringList titleList;
|
||||
if (wm_state) // don't do anything if WM_STATE doesn't exist
|
||||
windowTitles(windowRoot, titleList);
|
||||
return titleList;
|
||||
}
|
||||
|
||||
void AutoTypeGlobalX11::performGlobal(){
|
||||
bool wasLocked = mainWin->isLocked();
|
||||
if (wasLocked)
|
||||
mainWin->OnUnLockWorkspace();
|
||||
|
||||
if (!mainWin->isOpened())
|
||||
return;
|
||||
|
||||
Window w;
|
||||
int revert_to_return;
|
||||
XGetInputFocus(dpy, &w, &revert_to_return);
|
||||
char** list = NULL;
|
||||
int tree;
|
||||
do {
|
||||
XTextProperty textProp;
|
||||
if (XGetWMName(dpy, w, &textProp) != 0) {
|
||||
int count;
|
||||
if (Xutf8TextPropertyToTextList(dpy, &textProp, &list, &count)<0) return;
|
||||
if (list) break;
|
||||
}
|
||||
Window root = 0;
|
||||
Window parent = 0;
|
||||
Window* children = NULL;
|
||||
unsigned int num_children;
|
||||
tree = XQueryTree(dpy, w, &root, &parent, &children, &num_children);
|
||||
w = parent;
|
||||
if (children) XFree(children);
|
||||
} while (tree && w);
|
||||
if (!list) return;
|
||||
QString title = QString::fromUtf8(list[0]).toLower();
|
||||
XFreeStringList(list);
|
||||
|
||||
QList<IEntryHandle*> validEntries;
|
||||
QList<int> entryNumbers;
|
||||
QList<IEntryHandle*> entries = mainWin->db->entries();
|
||||
QRegExp lineMatch("Auto-Type-Window(?:-(\\d+)|):([^\\n]+)", Qt::CaseInsensitive, QRegExp::RegExp2);
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
for (int i=0; i<entries.size(); i++){
|
||||
if ( (entries[i]->expire()!=Date_Never && entries[i]->expire()<now) ||
|
||||
(getRootGroupName(entries[i]).compare("backup",Qt::CaseInsensitive)==0)
|
||||
){
|
||||
continue;
|
||||
}
|
||||
|
||||
bool hasWindowEntry=false;
|
||||
QString comment = entries[i]->comment();
|
||||
int offset = 0;
|
||||
while ( (offset=lineMatch.indexIn(comment, offset))!=-1 ){
|
||||
QStringList captured = lineMatch.capturedTexts();
|
||||
offset += captured[0].length();
|
||||
int nr;
|
||||
QString entryWindow;
|
||||
bool valid;
|
||||
if (captured.size()==2){
|
||||
nr = 0;
|
||||
entryWindow = captured[1].trimmed().toLower();
|
||||
}
|
||||
else{
|
||||
nr = captured[1].toInt();
|
||||
entryWindow = captured[2].trimmed().toLower();
|
||||
}
|
||||
if (entryWindow.length()==0) continue;
|
||||
|
||||
hasWindowEntry = true;
|
||||
bool wildStart = (entryWindow[0]=='*');
|
||||
bool wildEnd = (entryWindow[entryWindow.size()-1]=='*');
|
||||
if (wildStart&&wildEnd){
|
||||
entryWindow.remove(0,1);
|
||||
if (entryWindow.length()!=0){
|
||||
entryWindow.remove(entryWindow.size()-1,1);
|
||||
valid = title.contains(entryWindow);
|
||||
}
|
||||
else
|
||||
valid = true;
|
||||
}
|
||||
else if (wildStart){
|
||||
entryWindow.remove(0,1);
|
||||
valid = title.endsWith(entryWindow);
|
||||
}
|
||||
else if (wildEnd){
|
||||
entryWindow.remove(entryWindow.size()-1,1);
|
||||
valid = title.startsWith(entryWindow);
|
||||
}
|
||||
else {
|
||||
valid = (title==entryWindow);
|
||||
}
|
||||
|
||||
if (valid){
|
||||
validEntries << entries[i];
|
||||
entryNumbers << nr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasWindowEntry && config->entryTitlesMatch()){
|
||||
QString entryTitle = entries[i]->title().toLower();
|
||||
if (!entryTitle.isEmpty() && title.contains(entryTitle)){
|
||||
validEntries << entries[i];
|
||||
entryNumbers << 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (validEntries.size()==1){
|
||||
focusedWindow = NULL;
|
||||
perform(validEntries[0],wasLocked,entryNumbers[0],wasLocked);
|
||||
}
|
||||
else if (validEntries.size()>1){
|
||||
focusedWindow = w;
|
||||
AutoTypeDlg* dlg = new AutoTypeDlg(validEntries, entryNumbers, wasLocked);
|
||||
dlg->show();
|
||||
}
|
||||
}
|
||||
|
||||
bool AutoTypeGlobalX11::registerGlobalShortcut(const Shortcut& s){
|
||||
if (s.key==shortcut.key && s.ctrl==shortcut.ctrl && s.shift==shortcut.shift && s.alt==shortcut.alt && s.altgr==shortcut.altgr && s.win==shortcut.win)
|
||||
return true;
|
||||
|
||||
int code=XKeysymToKeycode(dpy, HelperX11::getKeysym(s.key));
|
||||
int mod=HelperX11::getShortcutModifierMask(s);
|
||||
|
||||
HelperX11::startCatchErrors();
|
||||
XGrabKey(dpy, code, mod, windowRoot, true, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(dpy, code, mod | Mod2Mask, windowRoot, true, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(dpy, code, mod | LockMask, windowRoot, true, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(dpy, code, mod | Mod2Mask | LockMask, windowRoot, true, GrabModeAsync, GrabModeAsync);
|
||||
HelperX11::stopCatchErrors();
|
||||
|
||||
if (HelperX11::errorOccurred()){
|
||||
XUngrabKey(dpy, code, mod, windowRoot);
|
||||
XUngrabKey(dpy, code, mod | Mod2Mask, windowRoot);
|
||||
XUngrabKey(dpy, code, mod | LockMask, windowRoot);
|
||||
XUngrabKey(dpy, code, mod | Mod2Mask | LockMask, windowRoot);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
unregisterGlobalShortcut();
|
||||
shortcut = s;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void AutoTypeGlobalX11::unregisterGlobalShortcut(){
|
||||
if (shortcut.key==0) return;
|
||||
|
||||
int code=XKeysymToKeycode(dpy, HelperX11::getKeysym(shortcut.key));
|
||||
int mod=HelperX11::getShortcutModifierMask(shortcut);
|
||||
|
||||
XUngrabKey(dpy, code, mod, windowRoot);
|
||||
XUngrabKey(dpy, code, mod | Mod2Mask, windowRoot);
|
||||
XUngrabKey(dpy, code, mod | LockMask, windowRoot);
|
||||
XUngrabKey(dpy, code, mod | Mod2Mask | LockMask, windowRoot);
|
||||
|
||||
shortcut.key = 0;
|
||||
}
|
||||
|
||||
QString AutoTypeGlobalX11::getRootGroupName(IEntryHandle* entry){
|
||||
IGroupHandle* group = entry->group();
|
||||
int level = group->level();
|
||||
for (int i=0; i<level; i++)
|
||||
group = group->parent();
|
||||
|
||||
return group->title();
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005-2008 by Tarek Saidi, Felix Geyer *
|
||||
* tarek.saidi@arcor.de *
|
||||
* *
|
||||
* 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; version 2 of the License. *
|
||||
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _AUTOTYPEGLOBALX11_H_
|
||||
#define _AUTOTYPEGLOBALX11_H_
|
||||
|
||||
#include "AutoTypeX11.h"
|
||||
|
||||
class AutoTypeGlobalX11 : public AutoTypeX11, public AutoTypeGlobal {
|
||||
public:
|
||||
AutoTypeGlobalX11(KeepassMainWindow* mainWin);
|
||||
void perform(IEntryHandle* entry, bool hideWindow=true, int nr=0, bool wasLocked=false);
|
||||
void performGlobal();
|
||||
bool registerGlobalShortcut(const Shortcut& s);
|
||||
void unregisterGlobalShortcut();
|
||||
QStringList getAllWindowTitles();
|
||||
|
||||
private:
|
||||
void windowTitles(Window window, QStringList& titleList);
|
||||
QString getRootGroupName(IEntryHandle* entry);
|
||||
|
||||
Window windowRoot;
|
||||
//QSet<QString> windowBlacklist;
|
||||
QSet<QString> classBlacklist;
|
||||
Atom wm_state;
|
||||
Window focusedWindow;
|
||||
};
|
||||
|
||||
#endif // _AUTOTYPEGLOBALX11_H_
|
|
@ -0,0 +1,866 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005-2008 by Tarek Saidi, Felix Geyer *
|
||||
* tarek.saidi@arcor.de *
|
||||
* *
|
||||
* 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; version 2 of the License. *
|
||||
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "AutoTypeX11.h"
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "lib/HelperX11.h"
|
||||
#include <QX11Info>
|
||||
|
||||
#ifndef GLOBAL_AUTOTYPE
|
||||
AutoType* autoType = NULL;
|
||||
|
||||
void initAutoType(KeepassMainWindow* mainWin) {
|
||||
autoType = new AutoTypeX11(mainWin);
|
||||
}
|
||||
#endif
|
||||
|
||||
AutoTypeAction::AutoTypeAction(AutoTypeActionType t, quint16 d) : type(t), data(d){
|
||||
}
|
||||
|
||||
bool AutoTypeX11::error_detected = false;
|
||||
|
||||
AutoTypeX11::AutoTypeX11(KeepassMainWindow* mainWin) {
|
||||
this->mainWin = mainWin;
|
||||
dpy = mainWin->x11Info().display();
|
||||
|
||||
keysym_table = NULL;
|
||||
alt_mask = 0;
|
||||
meta_mask = 0;
|
||||
altgr_mask = 0;
|
||||
altgr_keysym = NoSymbol;
|
||||
focused_window = None;
|
||||
focused_subwindow = None;
|
||||
|
||||
ReadKeymap();
|
||||
if (!altgr_mask)
|
||||
AddModifier(XK_Mode_switch);
|
||||
}
|
||||
|
||||
void AutoTypeX11::perform(IEntryHandle* entry, bool hideWindow, int nr, bool wasLocked){
|
||||
QString indexStr;
|
||||
if (nr==0)
|
||||
indexStr = "Auto-Type:";
|
||||
else
|
||||
indexStr = QString("Auto-Type-%1:").arg(nr);
|
||||
QString str;
|
||||
QString comment=entry->comment();
|
||||
int c=comment.count(indexStr, Qt::CaseInsensitive);
|
||||
if(c>1) {
|
||||
qWarning("More than one 'Auto-Type:' key sequence found.\nAllowed is only one per entry.");
|
||||
return;
|
||||
}
|
||||
else if (c==1) {
|
||||
int start = comment.indexOf(indexStr,0,Qt::CaseInsensitive) + indexStr.length();
|
||||
int end = comment.indexOf("\n", start);
|
||||
if (end == -1)
|
||||
end = comment.length();
|
||||
|
||||
str=comment.mid(start,end-start).trimmed();
|
||||
if (str.isEmpty())
|
||||
return;
|
||||
}
|
||||
else {
|
||||
bool usernameEmpty = entry->username().trimmed().isEmpty();
|
||||
SecString password=entry->password();
|
||||
password.unlock();
|
||||
bool passwordEmpty = password.string().trimmed().isEmpty();
|
||||
if (usernameEmpty && passwordEmpty)
|
||||
return;
|
||||
else if (usernameEmpty)
|
||||
str="{PASSWORD}{ENTER}";
|
||||
else if (passwordEmpty)
|
||||
str="{USERNAME}{ENTER}";
|
||||
else
|
||||
str="{USERNAME}{TAB}{PASSWORD}{ENTER}";
|
||||
}
|
||||
|
||||
QList<AutoTypeAction> Keys;
|
||||
for(int i=0;i<str.size();i++){
|
||||
if(str[i]=='{'){
|
||||
QString tmpl;
|
||||
i++;
|
||||
while(str[i]!='}' && i<str.size()){
|
||||
tmpl += str[i];
|
||||
i++;
|
||||
}
|
||||
if(i>=str.size()){
|
||||
qWarning("Syntax Error in Auto-Type sequence near character %d\nFound '{' without closing '}'", i+10);
|
||||
return;
|
||||
}
|
||||
templateToKeysyms(tmpl.toLower(),Keys,entry);
|
||||
continue;
|
||||
}
|
||||
else{
|
||||
Keys << AutoTypeAction(TypeKey, str[i].unicode());
|
||||
}
|
||||
}
|
||||
|
||||
if (hideWindow)
|
||||
mainWin->hide();
|
||||
|
||||
QApplication::processEvents();
|
||||
sleepTime(config->autoTypePreGap());
|
||||
|
||||
QString type;
|
||||
for(int i=0;i<Keys.size();i++){
|
||||
if (Keys[i].type==TypeKey){
|
||||
SendKeyPressedEvent(Keys[i].data, 0);
|
||||
sleepKeyStrokeDelay();
|
||||
}
|
||||
else if (Keys[i].type==Delay){
|
||||
QApplication::processEvents();
|
||||
sleepTime(Keys[i].data);
|
||||
}
|
||||
}
|
||||
|
||||
if (config->lockOnMinimize()){
|
||||
if (hideWindow || wasLocked){
|
||||
if ( !(config->showSysTrayIcon() && config->minimizeTray()) )
|
||||
mainWin->showMinimized();
|
||||
else
|
||||
mainWin->OnUnLockWorkspace();
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (hideWindow && !(config->showSysTrayIcon() && config->minimizeTray()) )
|
||||
mainWin->showMinimized();
|
||||
if (wasLocked)
|
||||
mainWin->OnUnLockWorkspace();
|
||||
}
|
||||
}
|
||||
|
||||
void AutoTypeX11::sleepTime(int msec){
|
||||
if (msec==0) return;
|
||||
timespec timeOut, remains;
|
||||
timeOut.tv_sec = msec/1000;
|
||||
timeOut.tv_nsec = (msec%1000)*1000000;
|
||||
nanosleep(&timeOut, &remains);
|
||||
}
|
||||
|
||||
void AutoTypeX11::templateToKeysyms(const QString& tmpl, QList<AutoTypeAction>& keys,IEntryHandle* entry){
|
||||
//tmpl must be lower case!!!
|
||||
if(!tmpl.compare("title")){
|
||||
stringToKeysyms(entry->title(),keys);
|
||||
return;
|
||||
}
|
||||
if(!tmpl.compare("username")){
|
||||
stringToKeysyms(entry->username(),keys);
|
||||
return;
|
||||
}
|
||||
if(!tmpl.compare("url")){
|
||||
stringToKeysyms(entry->url(),keys);
|
||||
return;
|
||||
}
|
||||
if(!tmpl.compare("password")){
|
||||
SecString password=entry->password();
|
||||
password.unlock();
|
||||
stringToKeysyms(password,keys);
|
||||
return;
|
||||
}
|
||||
if(!tmpl.compare("space")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym(' '));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("backspace") || !tmpl.compare("bs") || !tmpl.compare("bksp")){
|
||||
keys << AutoTypeAction(TypeKey, XK_BackSpace);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("break")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Break);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("capslock")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Caps_Lock);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("del") || !tmpl.compare("delete")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Delete);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("end")){
|
||||
keys << AutoTypeAction(TypeKey, XK_End);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("enter")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Return);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("esc")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Escape);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("help")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Help);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("home")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Home);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("insert") || !tmpl.compare("ins")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Insert);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("numlock")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Num_Lock);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("scroll")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Scroll_Lock);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("pgdn")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Page_Down);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("pgup")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Page_Up);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("prtsc")){
|
||||
keys << AutoTypeAction(TypeKey, XK_3270_PrintScreen);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("up")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Up);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("down")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Down);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("left")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Left);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("right")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Right);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("f1")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F1);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("f2")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F2);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("f3")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F3);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("f4")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F4);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("f5")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F5);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("f6")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F6);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("f7")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F7);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("f8")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F8);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("f9")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F9);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("f10")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F10);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("f11")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F11);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("f12")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F12);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("f13")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F13);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("f14")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F14);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("f15")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F15);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("f16")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F16);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("add") || !tmpl.compare("plus")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('+'));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("subtract")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('-'));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("multiply")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('+'));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("divide")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('/'));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("at")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('@'));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("percent")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('%'));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("caret")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('^'));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("tilde")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('~'));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("leftbrace")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('{'));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("rightbrace")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('}'));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("leftparen")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('('));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("rightparen")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym(')'));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("winl")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Super_L);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("winr")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Super_R);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("win")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Super_L);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tmpl.compare("tab")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Tab);
|
||||
return;
|
||||
}
|
||||
|
||||
if(tmpl.startsWith("delay ") && tmpl.length()>6){
|
||||
bool ok;
|
||||
quint16 delay = tmpl.right(tmpl.length()-6).toInt(&ok);
|
||||
if (ok && delay>0 && delay<=10000)
|
||||
keys << AutoTypeAction(Delay, delay);
|
||||
}
|
||||
}
|
||||
|
||||
void AutoTypeX11::stringToKeysyms(const QString& string,QList<AutoTypeAction>& KeySymList){
|
||||
for(int i=0; i<string.length();i++)
|
||||
KeySymList << AutoTypeAction(TypeKey, HelperX11::getKeysym(string[i]));
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// The following code is taken from xvkbd and has been slightly modified.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* xvkbd - Virtual Keyboard for X Window System
|
||||
* (Version 3.0, 2008-05-05)
|
||||
*
|
||||
* Copyright (C) 2000-2008 by Tom Sato <VEF00200@nifty.ne.jp>
|
||||
* http://homepage3.nifty.com/tsato/
|
||||
*
|
||||
* 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 any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Insert a specified keysym to unused position in the keymap table.
|
||||
* This will be called to add required keysyms on-the-fly.
|
||||
* if the second parameter is TRUE, the keysym will be added to the
|
||||
* non-shifted position - this may be required for modifier keys
|
||||
* (e.g. Mode_switch) and some special keys (e.g. F20).
|
||||
*/
|
||||
int AutoTypeX11::AddKeysym(KeySym keysym, bool top)
|
||||
{
|
||||
int keycode, pos, max_pos, inx, phase;
|
||||
|
||||
if (top) {
|
||||
max_pos = 0;
|
||||
} else {
|
||||
max_pos = keysym_per_keycode - 1;
|
||||
if (4 <= max_pos) max_pos = 3;
|
||||
if (2 <= max_pos && altgr_keysym != XK_Mode_switch) max_pos = 1;
|
||||
}
|
||||
|
||||
for (phase = 0; phase < 2; phase++) {
|
||||
for (keycode = max_keycode; min_keycode <= keycode; keycode--) {
|
||||
for (pos = max_pos; 0 <= pos; pos--) {
|
||||
inx = (keycode - min_keycode) * keysym_per_keycode;
|
||||
if ((phase != 0 || keysym_table[inx] == NoSymbol) && keysym_table[inx] < 0xFF00) {
|
||||
/* In the first phase, to avoid modifing existing keys, */
|
||||
/* add the keysym only to the keys which has no keysym in the first position. */
|
||||
/* If no place fuond in the first phase, add the keysym for any keys except */
|
||||
/* for modifier keys and other special keys */
|
||||
if (keysym_table[inx + pos] == NoSymbol) {
|
||||
keysym_table[inx + pos] = keysym;
|
||||
XChangeKeyboardMapping(dpy, keycode, keysym_per_keycode, &keysym_table[inx], 1);
|
||||
XFlush(dpy);
|
||||
return keycode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
qWarning("Couldn't add \"%s\" to keymap", XKeysymToString(keysym));
|
||||
return NoSymbol;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the specified key as a new modifier.
|
||||
* This is used to use Mode_switch (AltGr) as a modifier.
|
||||
*/
|
||||
void AutoTypeX11::AddModifier(KeySym keysym)
|
||||
{
|
||||
XModifierKeymap *modifiers;
|
||||
int keycode, i, pos;
|
||||
|
||||
keycode = XKeysymToKeycode(dpy, keysym);
|
||||
if (keycode == NoSymbol) keycode = AddKeysym(keysym, TRUE);
|
||||
|
||||
modifiers = XGetModifierMapping(dpy);
|
||||
for (i = 7; 3 < i; i--) {
|
||||
if (modifiers->modifiermap[i * modifiers->max_keypermod] == NoSymbol
|
||||
|| ((keysym_table[(modifiers->modifiermap[i * modifiers->max_keypermod]
|
||||
- min_keycode) * keysym_per_keycode]) == XK_ISO_Level3_Shift
|
||||
&& keysym == XK_Mode_switch))
|
||||
{
|
||||
for (pos = 0; pos < modifiers->max_keypermod; pos++) {
|
||||
if (modifiers->modifiermap[i * modifiers->max_keypermod + pos] == NoSymbol) {
|
||||
modifiers->modifiermap[i * modifiers->max_keypermod + pos] = keycode;
|
||||
XSetModifierMapping(dpy, modifiers);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
qWarning("Couldn't add \"%s\" as modifier", XKeysymToString(keysym));
|
||||
}
|
||||
|
||||
/*
|
||||
* Read keyboard mapping and modifier mapping.
|
||||
* Keyboard mapping is used to know what keys are in shifted position.
|
||||
* Modifier mapping is required because we should know Alt and Meta
|
||||
* key are used as which modifier.
|
||||
*/
|
||||
void AutoTypeX11::ReadKeymap()
|
||||
{
|
||||
int i;
|
||||
int keycode, inx, pos;
|
||||
KeySym keysym;
|
||||
XModifierKeymap *modifiers;
|
||||
int last_altgr_mask;
|
||||
|
||||
XDisplayKeycodes(dpy, &min_keycode, &max_keycode);
|
||||
if (keysym_table != NULL) XFree(keysym_table);
|
||||
keysym_table = XGetKeyboardMapping(dpy,
|
||||
min_keycode, max_keycode - min_keycode + 1,
|
||||
&keysym_per_keycode);
|
||||
for (keycode = min_keycode; keycode <= max_keycode; keycode++) {
|
||||
/* if the first keysym is alphabet and the second keysym is NoSymbol,
|
||||
it is equivalent to pair of lowercase and uppercase alphabet */
|
||||
inx = (keycode - min_keycode) * keysym_per_keycode;
|
||||
if (keysym_table[inx + 1] == NoSymbol
|
||||
&& ((XK_A <= keysym_table[inx] && keysym_table[inx] <= XK_Z)
|
||||
|| (XK_a <= keysym_table[inx] && keysym_table[inx] <= XK_z)))
|
||||
{
|
||||
if (XK_A <= keysym_table[inx] && keysym_table[inx] <= XK_Z)
|
||||
keysym_table[inx] = keysym_table[inx] - XK_A + XK_a;
|
||||
keysym_table[inx + 1] = keysym_table[inx] - XK_a + XK_A;
|
||||
}
|
||||
}
|
||||
|
||||
last_altgr_mask = altgr_mask;
|
||||
alt_mask = 0;
|
||||
meta_mask = 0;
|
||||
altgr_mask = 0;
|
||||
altgr_keysym = NoSymbol;
|
||||
modifiers = XGetModifierMapping(dpy);
|
||||
for (i = 0; i < 8; i++) {
|
||||
for (pos = 0; pos < modifiers->max_keypermod; pos++) {
|
||||
keycode = modifiers->modifiermap[i * modifiers->max_keypermod + pos];
|
||||
if (keycode < min_keycode || max_keycode < keycode) continue;
|
||||
|
||||
keysym = keysym_table[(keycode - min_keycode) * keysym_per_keycode];
|
||||
if (keysym == XK_Alt_L || keysym == XK_Alt_R) {
|
||||
alt_mask = 1 << i;
|
||||
} else if (keysym == XK_Meta_L || keysym == XK_Meta_R) {
|
||||
meta_mask = 1 << i;
|
||||
} else if (keysym == XK_Mode_switch) {
|
||||
if (altgr_keysym == XK_ISO_Level3_Shift) {
|
||||
} else {
|
||||
altgr_mask = 0x0101 << i;
|
||||
/* I don't know why, but 0x2000 was required for mod3 on my Linux box */
|
||||
altgr_keysym = keysym;
|
||||
}
|
||||
} else if (keysym == XK_ISO_Level3_Shift) {
|
||||
/* if no Mode_switch, try to use ISO_Level3_Shift instead */
|
||||
/* however, it may not work as intended - I don't know why */
|
||||
altgr_mask = 1 << i;
|
||||
altgr_keysym = keysym;
|
||||
}
|
||||
}
|
||||
}
|
||||
XFreeModifiermap(modifiers);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send event to the focused window.
|
||||
* If input focus is specified explicitly, select the window
|
||||
* before send event to the window.
|
||||
*/
|
||||
void AutoTypeX11::SendEvent(XKeyEvent *event)
|
||||
{
|
||||
static bool first = TRUE;
|
||||
|
||||
XSync(event->display, FALSE);
|
||||
int (*oldHandler) (Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler);
|
||||
|
||||
error_detected = FALSE;
|
||||
if (focused_window != None) {
|
||||
/* set input focus if input focus is set explicitly */
|
||||
XSetInputFocus(event->display, focused_window, RevertToParent, CurrentTime);
|
||||
XSync(event->display, FALSE);
|
||||
}
|
||||
if (!error_detected) {
|
||||
Window root, child, w;
|
||||
int root_x, root_y, x, y;
|
||||
unsigned int mask;
|
||||
int revert_to;
|
||||
|
||||
w = None;
|
||||
first = FALSE;
|
||||
|
||||
w = focused_subwindow;
|
||||
if (w == None)
|
||||
XGetInputFocus(event->display, &w, &revert_to);
|
||||
|
||||
if (w != None) {
|
||||
XQueryPointer(event->display, w,
|
||||
&root, &child, &root_x, &root_y, &x, &y, &mask);
|
||||
XWarpPointer(event->display, None, w, 0, 0, 0, 0, 1, 1);
|
||||
XFlush(event->display);
|
||||
}
|
||||
|
||||
XTestFakeKeyEvent(event->display, event->keycode, event->type == KeyPress, 0);
|
||||
XFlush(event->display);
|
||||
|
||||
if (w != None) {
|
||||
XWarpPointer(event->display, None, root, 0, 0, 0, 0, root_x, root_y);
|
||||
XFlush(event->display);
|
||||
}
|
||||
} else {
|
||||
XTestFakeKeyEvent(event->display, event->keycode, event->type == KeyPress, 0);
|
||||
XFlush(event->display);
|
||||
}
|
||||
|
||||
if (error_detected) {
|
||||
/* reset focus because focused window is (probably) no longer exist */
|
||||
focused_window = None;
|
||||
focused_subwindow = None;
|
||||
}
|
||||
|
||||
XSetErrorHandler(oldHandler);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send sequence of KeyPressed/KeyReleased events to the focused
|
||||
* window to simulate keyboard. If modifiers (shift, control, etc)
|
||||
* are set ON, many events will be sent.
|
||||
*/
|
||||
void AutoTypeX11::SendKeyPressedEvent(KeySym keysym, unsigned int shift)
|
||||
{
|
||||
Window cur_focus;
|
||||
int revert_to;
|
||||
XKeyEvent event;
|
||||
int keycode;
|
||||
int phase, inx;
|
||||
bool found;
|
||||
|
||||
if (focused_subwindow != None)
|
||||
cur_focus = focused_subwindow;
|
||||
else
|
||||
XGetInputFocus(dpy, &cur_focus, &revert_to);
|
||||
|
||||
found = FALSE;
|
||||
keycode = 0;
|
||||
if (keysym != NoSymbol) {
|
||||
for (phase = 0; phase < 2; phase++) {
|
||||
for (keycode = min_keycode; !found && (keycode <= max_keycode); keycode++) {
|
||||
/* Determine keycode for the keysym: we use this instead
|
||||
of XKeysymToKeycode() because we must know shift_state, too */
|
||||
inx = (keycode - min_keycode) * keysym_per_keycode;
|
||||
if (keysym_table[inx] == keysym) {
|
||||
shift &= ~altgr_mask;
|
||||
if (keysym_table[inx + 1] != NoSymbol) shift &= ~ShiftMask;
|
||||
found = TRUE;
|
||||
break;
|
||||
} else if (keysym_table[inx + 1] == keysym) {
|
||||
shift &= ~altgr_mask;
|
||||
shift |= ShiftMask;
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found && altgr_mask && 3 <= keysym_per_keycode) {
|
||||
for (keycode = min_keycode; !found && (keycode <= max_keycode); keycode++) {
|
||||
inx = (keycode - min_keycode) * keysym_per_keycode;
|
||||
if (keysym_table[inx + 2] == keysym) {
|
||||
shift &= ~ShiftMask;
|
||||
shift |= altgr_mask;
|
||||
found = TRUE;
|
||||
break;
|
||||
} else if (4 <= keysym_per_keycode && keysym_table[inx + 3] == keysym) {
|
||||
shift |= ShiftMask | altgr_mask;
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found) break;
|
||||
|
||||
if (0xF000 <= keysym) {
|
||||
/* for special keys such as function keys,
|
||||
first try to add it in the non-shifted position of the keymap */
|
||||
if (AddKeysym(keysym, TRUE) == NoSymbol) AddKeysym(keysym, FALSE);
|
||||
} else {
|
||||
AddKeysym(keysym, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event.display = dpy;
|
||||
event.window = cur_focus;
|
||||
event.root = RootWindow(event.display, DefaultScreen(event.display));
|
||||
event.subwindow = None;
|
||||
event.time = CurrentTime;
|
||||
event.x = 1;
|
||||
event.y = 1;
|
||||
event.x_root = 1;
|
||||
event.y_root = 1;
|
||||
event.same_screen = TRUE;
|
||||
|
||||
Window root, child;
|
||||
int root_x, root_y, x, y;
|
||||
unsigned int mask;
|
||||
|
||||
XQueryPointer(dpy, event.root, &root, &child, &root_x, &root_y, &x, &y, &mask);
|
||||
|
||||
event.type = KeyRelease;
|
||||
event.state = 0;
|
||||
if (mask & ControlMask) {
|
||||
event.keycode = XKeysymToKeycode(dpy, XK_Control_L);
|
||||
SendEvent(&event);
|
||||
}
|
||||
if (mask & alt_mask) {
|
||||
event.keycode = XKeysymToKeycode(dpy, XK_Alt_L);
|
||||
SendEvent(&event);
|
||||
}
|
||||
if (mask & meta_mask) {
|
||||
event.keycode = XKeysymToKeycode(dpy, XK_Meta_L);
|
||||
SendEvent(&event);
|
||||
}
|
||||
if (mask & altgr_mask) {
|
||||
event.keycode = XKeysymToKeycode(dpy, altgr_keysym);
|
||||
SendEvent(&event);
|
||||
}
|
||||
if (mask & ShiftMask) {
|
||||
event.keycode = XKeysymToKeycode(dpy, XK_Shift_L);
|
||||
SendEvent(&event);
|
||||
}
|
||||
if (mask & LockMask) {
|
||||
event.keycode = XKeysymToKeycode(dpy, XK_Caps_Lock);
|
||||
SendEvent(&event);
|
||||
}
|
||||
|
||||
event.type = KeyPress;
|
||||
event.state = 0;
|
||||
if (shift & ControlMask) {
|
||||
event.keycode = XKeysymToKeycode(dpy, XK_Control_L);
|
||||
SendEvent(&event);
|
||||
event.state |= ControlMask;
|
||||
}
|
||||
if (shift & alt_mask) {
|
||||
event.keycode = XKeysymToKeycode(dpy, XK_Alt_L);
|
||||
SendEvent(&event);
|
||||
event.state |= alt_mask;
|
||||
}
|
||||
if (shift & meta_mask) {
|
||||
event.keycode = XKeysymToKeycode(dpy, XK_Meta_L);
|
||||
SendEvent(&event);
|
||||
event.state |= meta_mask;
|
||||
}
|
||||
if (shift & altgr_mask) {
|
||||
event.keycode = XKeysymToKeycode(dpy, altgr_keysym);
|
||||
SendEvent(&event);
|
||||
event.state |= altgr_mask;
|
||||
}
|
||||
if (shift & ShiftMask) {
|
||||
event.keycode = XKeysymToKeycode(dpy, XK_Shift_L);
|
||||
SendEvent(&event);
|
||||
event.state |= ShiftMask;
|
||||
}
|
||||
|
||||
if (keysym != NoSymbol) { /* send event for the key itself */
|
||||
event.keycode = found ? keycode : XKeysymToKeycode(dpy, keysym);
|
||||
if (event.keycode == NoSymbol) {
|
||||
if ((keysym & ~0x7f) == 0 && isprint(keysym))
|
||||
qWarning("No such key: %c", (char)keysym);
|
||||
else if (XKeysymToString(keysym) != NULL)
|
||||
qWarning("No such key: keysym=%s (0x%lX)", XKeysymToString(keysym), (long)keysym);
|
||||
else
|
||||
qWarning("No such key: keysym=0x%lX", (long)keysym);
|
||||
} else {
|
||||
SendEvent(&event);
|
||||
event.type = KeyRelease;
|
||||
SendEvent(&event);
|
||||
}
|
||||
}
|
||||
|
||||
event.type = KeyRelease;
|
||||
if (shift & ShiftMask) {
|
||||
event.keycode = XKeysymToKeycode(dpy, XK_Shift_L);
|
||||
SendEvent(&event);
|
||||
event.state &= ~ShiftMask;
|
||||
}
|
||||
if (shift & altgr_mask) {
|
||||
event.keycode = XKeysymToKeycode(dpy, altgr_keysym);
|
||||
SendEvent(&event);
|
||||
event.state &= ~altgr_mask;
|
||||
}
|
||||
if (shift & meta_mask) {
|
||||
event.keycode = XKeysymToKeycode(dpy, XK_Meta_L);
|
||||
SendEvent(&event);
|
||||
event.state &= ~meta_mask;
|
||||
}
|
||||
if (shift & alt_mask) {
|
||||
event.keycode = XKeysymToKeycode(dpy, XK_Alt_L);
|
||||
SendEvent(&event);
|
||||
event.state &= ~alt_mask;
|
||||
}
|
||||
if (shift & ControlMask) {
|
||||
event.keycode = XKeysymToKeycode(dpy, XK_Control_L);
|
||||
SendEvent(&event);
|
||||
event.state &= ~ControlMask;
|
||||
}
|
||||
}
|
||||
|
||||
int AutoTypeX11::MyErrorHandler(Display *my_dpy, XErrorEvent *event)
|
||||
{
|
||||
char msg[200];
|
||||
|
||||
error_detected = TRUE;
|
||||
if (event->error_code == BadWindow) {
|
||||
return 0;
|
||||
}
|
||||
XGetErrorText(my_dpy, event->error_code, msg, sizeof(msg) - 1);
|
||||
qWarning("X error trapped: %s, request-code=%d\n", msg, event->request_code);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005-2008 by Tarek Saidi, Felix Geyer *
|
||||
* tarek.saidi@arcor.de *
|
||||
* *
|
||||
* 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; version 2 of the License. *
|
||||
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _AUTOTYPEX11_H_
|
||||
#define _AUTOTYPEX11_H_
|
||||
|
||||
#include "AutoType.h"
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
enum AutoTypeActionType{
|
||||
TypeKey, Delay
|
||||
};
|
||||
|
||||
struct AutoTypeAction{
|
||||
AutoTypeAction(AutoTypeActionType t, quint16 d);
|
||||
AutoTypeActionType type;
|
||||
quint16 data;
|
||||
};
|
||||
|
||||
class AutoTypeX11 : public AutoType {
|
||||
public:
|
||||
AutoTypeX11(KeepassMainWindow* mainWin);
|
||||
void perform(IEntryHandle* entry, bool hideWindow=true, int nr=0, bool wasLocked=false);
|
||||
|
||||
protected:
|
||||
void sleepTime(int msec);
|
||||
inline void sleepKeyStrokeDelay(){ sleep(config->autoTypeKeyStrokeDelay()); };
|
||||
void templateToKeysyms(const QString& Template, QList<AutoTypeAction>& KeySymList,IEntryHandle* entry);
|
||||
void stringToKeysyms(const QString& string,QList<AutoTypeAction>& KeySymList);
|
||||
|
||||
int AddKeysym(KeySym keysym, bool top);
|
||||
void AddModifier(KeySym keysym);
|
||||
void ReadKeymap();
|
||||
void SendKeyPressedEvent(KeySym keysym, unsigned int shift);
|
||||
void SendEvent(XKeyEvent *event);
|
||||
static int MyErrorHandler(Display *my_dpy, XErrorEvent *event);
|
||||
|
||||
KeepassMainWindow* mainWin;
|
||||
Display* dpy;
|
||||
|
||||
KeySym *keysym_table;
|
||||
int min_keycode, max_keycode;
|
||||
int keysym_per_keycode;
|
||||
static bool error_detected;
|
||||
int alt_mask;
|
||||
int meta_mask;
|
||||
int altgr_mask;
|
||||
KeySym altgr_keysym;
|
||||
Window focused_window;
|
||||
Window focused_subwindow;
|
||||
};
|
||||
|
||||
#endif // _AUTOTYPEX11_H_
|
|
@ -1,665 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005-2006 by Tarek Saidi, Felix Geyer *
|
||||
* tarek.saidi@arcor.de *
|
||||
* *
|
||||
* 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; version 2 of the License. *
|
||||
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include <QX11Info>
|
||||
#include <X11/Xutil.h>
|
||||
#include "mainwindow.h"
|
||||
#include "HelperX11.h"
|
||||
#include "AutoType.h"
|
||||
|
||||
#ifdef GLOBAL_AUTOTYPE
|
||||
#include "dialogs/AutoTypeDlg.h"
|
||||
#endif
|
||||
|
||||
enum AutoTypeActionType{
|
||||
TypeKey, Delay
|
||||
};
|
||||
|
||||
struct AutoTypeAction{
|
||||
AutoTypeAction(AutoTypeActionType t, quint16 d);
|
||||
AutoTypeActionType type;
|
||||
quint16 data;
|
||||
};
|
||||
|
||||
class AutoTypePrivate{
|
||||
public:
|
||||
static void sleep(int msec);
|
||||
inline static void sleepKeyStrokeDelay(){ sleep(config->autoTypeKeyStrokeDelay()); };
|
||||
static void templateToKeysyms(const QString& Template, QList<AutoTypeAction>& KeySymList,IEntryHandle* entry);
|
||||
static void stringToKeysyms(const QString& string,QList<AutoTypeAction>& KeySymList);
|
||||
static QString getRootGroupName(IEntryHandle* entry);
|
||||
};
|
||||
|
||||
|
||||
// AutoType
|
||||
|
||||
KeepassMainWindow* AutoType::MainWin=NULL;
|
||||
#ifdef GLOBAL_AUTOTYPE
|
||||
Shortcut AutoType::shortcut;
|
||||
#endif
|
||||
|
||||
void AutoType::perform(IEntryHandle* entry, QString& err,bool hideWindow,int nr,bool wasLocked){
|
||||
QString indexStr;
|
||||
if (nr==0)
|
||||
indexStr = "Auto-Type:";
|
||||
else
|
||||
indexStr = QString("Auto-Type-%1:").arg(nr);
|
||||
QString str;
|
||||
QString comment=entry->comment();
|
||||
int c=comment.count(indexStr, Qt::CaseInsensitive);
|
||||
if(c>1){
|
||||
err=QCoreApplication::translate("AutoType","More than one 'Auto-Type:' key sequence found.\nAllowed is only one per entry.");
|
||||
return;
|
||||
}
|
||||
else if(c==1){
|
||||
int start = comment.indexOf(indexStr,0,Qt::CaseInsensitive) + indexStr.length();
|
||||
int end = comment.indexOf("\n", start);
|
||||
if (end == -1)
|
||||
end = comment.length();
|
||||
|
||||
str=comment.mid(start,end-start).trimmed();
|
||||
if (str.isEmpty())
|
||||
return;
|
||||
}
|
||||
else
|
||||
str="{USERNAME}{TAB}{PASSWORD}{ENTER}";
|
||||
|
||||
QList<AutoTypeAction> Keys;
|
||||
for(int i=0;i<str.size();i++){
|
||||
if(str[i]=='{'){
|
||||
QString tmpl;
|
||||
i++;
|
||||
while(str[i]!='}' && i<str.size()){
|
||||
tmpl += str[i];
|
||||
i++;
|
||||
}
|
||||
if(i>=str.size()){
|
||||
err=QCoreApplication::translate("AutoType","Syntax Error in Auto-Type sequence near character %1\n\
|
||||
Found '{' without closing '}'").arg(i+10);
|
||||
return;
|
||||
}
|
||||
AutoTypePrivate::templateToKeysyms(tmpl.toLower(),Keys,entry);
|
||||
continue;
|
||||
}
|
||||
else{
|
||||
Keys << AutoTypeAction(TypeKey, HelperX11::getKeysym(str[i]));
|
||||
}
|
||||
}
|
||||
|
||||
if (hideWindow)
|
||||
MainWin->hide();
|
||||
|
||||
AutoTypePrivate::sleep(config->autoTypePreGap());
|
||||
|
||||
Display* pDisplay = QX11Info::display();
|
||||
|
||||
bool capsEnabled = HelperX11::keyboardModifiers(pDisplay)&LockMask;
|
||||
if (capsEnabled){
|
||||
XTestFakeKeyEvent(pDisplay,XKeysymToKeycode(pDisplay,XK_Caps_Lock),true,0);
|
||||
XTestFakeKeyEvent(pDisplay,XKeysymToKeycode(pDisplay,XK_Caps_Lock),false,0);
|
||||
AutoTypePrivate::sleepKeyStrokeDelay();
|
||||
}
|
||||
|
||||
char keys_return[32];
|
||||
XQueryKeymap(pDisplay, keys_return);
|
||||
for (int i=0; i<32; i++)
|
||||
for (int j=0; j<8; j++)
|
||||
if ( keys_return[i] & (1<<j) ){
|
||||
XTestFakeKeyEvent(pDisplay,i*8+j,false,2);
|
||||
AutoTypePrivate::sleepKeyStrokeDelay();
|
||||
}
|
||||
|
||||
for(int i=0;i<Keys.size();i++){
|
||||
if (Keys[i].type==TypeKey){
|
||||
int keycode=XKeysymToKeycode(pDisplay,Keys[i].data);
|
||||
if (keycode==0){
|
||||
err = QCoreApplication::translate("AutoType","Auto-Type string contains invalid characters");
|
||||
break;
|
||||
}
|
||||
int mods=HelperX11::getModifiers(pDisplay,Keys[i].data,keycode);
|
||||
HelperX11::pressModifiers(pDisplay,mods);
|
||||
AutoTypePrivate::sleepKeyStrokeDelay();
|
||||
XTestFakeKeyEvent(pDisplay,keycode,True,0);
|
||||
AutoTypePrivate::sleepKeyStrokeDelay();
|
||||
XTestFakeKeyEvent(pDisplay,keycode,False,1);
|
||||
AutoTypePrivate::sleepKeyStrokeDelay();
|
||||
HelperX11::releaseModifiers(pDisplay,mods);
|
||||
AutoTypePrivate::sleepKeyStrokeDelay();
|
||||
}
|
||||
else if (Keys[i].type==Delay){
|
||||
QApplication::processEvents();
|
||||
AutoTypePrivate::sleep(Keys[i].data);
|
||||
}
|
||||
}
|
||||
|
||||
if (capsEnabled){
|
||||
XTestFakeKeyEvent(pDisplay,XKeysymToKeycode(pDisplay,XK_Caps_Lock),true,0);
|
||||
XTestFakeKeyEvent(pDisplay,XKeysymToKeycode(pDisplay,XK_Caps_Lock),false,0);
|
||||
}
|
||||
|
||||
if (config->lockOnMinimize()){
|
||||
if (hideWindow || wasLocked){
|
||||
if ( !(config->showSysTrayIcon() && config->minimizeTray()) )
|
||||
MainWin->showMinimized();
|
||||
else
|
||||
MainWin->OnUnLockWorkspace();
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (hideWindow && !(config->showSysTrayIcon() && config->minimizeTray()) )
|
||||
MainWin->showMinimized();
|
||||
if (wasLocked)
|
||||
MainWin->OnUnLockWorkspace();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GLOBAL_AUTOTYPE
|
||||
|
||||
Window windowRoot;
|
||||
//QSet<QString> windowBlacklist;
|
||||
QSet<QString> classBlacklist;
|
||||
Atom wm_state;
|
||||
|
||||
void windowTitles(Window window, QStringList& titleList){
|
||||
Display* d = QX11Info::display();
|
||||
|
||||
Atom type = None;
|
||||
int format;
|
||||
unsigned long nitems, after;
|
||||
unsigned char* data;
|
||||
XGetWindowProperty(d, window, wm_state, 0, 0, false, AnyPropertyType, &type, &format, &nitems, &after, &data);
|
||||
if (type){
|
||||
XTextProperty textProp;
|
||||
if (XGetWMName(d, window, &textProp) != 0) {
|
||||
char** list = NULL;
|
||||
int count;
|
||||
if (Xutf8TextPropertyToTextList(d, &textProp, &list, &count)>=0 && list){
|
||||
QString title = QString::fromUtf8(list[0]);
|
||||
|
||||
QString className;
|
||||
XClassHint* wmClass = XAllocClassHint();
|
||||
if (XGetClassHint(d, window, wmClass)!=0 && wmClass->res_name!=NULL)
|
||||
className = QString::fromLocal8Bit(wmClass->res_name);
|
||||
XFree(wmClass);
|
||||
|
||||
if (window!=windowRoot && window!=AutoType::MainWin->winId() &&
|
||||
(QApplication::activeWindow()==NULL || window!=QApplication::activeWindow()->winId()) &&
|
||||
// !windowBlacklist.contains(title) &&
|
||||
(className.isNull() || !classBlacklist.contains(className))
|
||||
){
|
||||
titleList.append(title);
|
||||
}
|
||||
XFreeStringList(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Window root;
|
||||
Window parent;
|
||||
Window* children = NULL;
|
||||
unsigned int num_children;
|
||||
int tree = XQueryTree(d, window, &root, &parent, &children, &num_children);
|
||||
if (tree && children){
|
||||
for (int i=0; i<num_children; i++)
|
||||
windowTitles(children[i], titleList);
|
||||
}
|
||||
else
|
||||
XFree(children);
|
||||
}
|
||||
|
||||
void AutoType::init(){
|
||||
Display* d = QX11Info::display();
|
||||
wm_state = XInternAtom(d, "WM_STATE", true);
|
||||
windowRoot = XRootWindow(d, MainWin->x11Info().screen());
|
||||
//windowBlacklist << "kicker" << "KDE Desktop";
|
||||
classBlacklist << "desktop_window" << "gnome-panel"; // Gnome
|
||||
classBlacklist << "kdesktop" << "kicker"; // KDE 3
|
||||
classBlacklist << "xfdesktop" << "xfce4-panel"; // Xfce 4
|
||||
}
|
||||
|
||||
QStringList AutoType::getAllWindowTitles(){
|
||||
QStringList titleList;
|
||||
if (wm_state) // don't do anything if WM_STATE doesn't exist
|
||||
windowTitles(windowRoot, titleList);
|
||||
return titleList;
|
||||
}
|
||||
|
||||
void AutoType::performGlobal(){
|
||||
bool wasLocked = MainWin->isLocked();
|
||||
if (wasLocked)
|
||||
MainWin->OnUnLockWorkspace();
|
||||
|
||||
if (!MainWin->isOpened())
|
||||
return;
|
||||
|
||||
Display* d = QX11Info::display();
|
||||
Window w;
|
||||
int revert_to_return;
|
||||
XGetInputFocus(d, &w, &revert_to_return);
|
||||
char** list = NULL;
|
||||
int tree;
|
||||
do {
|
||||
XTextProperty textProp;
|
||||
if (XGetWMName(d, w, &textProp) != 0) {
|
||||
int count;
|
||||
if (Xutf8TextPropertyToTextList(d, &textProp, &list, &count)<0) return;
|
||||
if (list) break;
|
||||
}
|
||||
Window root = 0;
|
||||
Window parent = 0;
|
||||
Window* children = NULL;
|
||||
unsigned int num_children;
|
||||
tree = XQueryTree(d, w, &root, &parent, &children, &num_children);
|
||||
w = parent;
|
||||
if (children) XFree(children);
|
||||
} while (tree && w);
|
||||
if (!list) return;
|
||||
QString title = QString::fromUtf8(list[0]).toLower();
|
||||
XFreeStringList(list);
|
||||
|
||||
QList<IEntryHandle*> validEntries;
|
||||
QList<int> entryNumbers;
|
||||
QList<IEntryHandle*> entries = MainWin->db->entries();
|
||||
QRegExp lineMatch("Auto-Type-Window(?:-(\\d+)|):([^\\n]+)", Qt::CaseInsensitive, QRegExp::RegExp2);
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
for (int i=0; i<entries.size(); i++){
|
||||
if ( (entries[i]->expire()!=Date_Never && entries[i]->expire()<now) ||
|
||||
(AutoTypePrivate::getRootGroupName(entries[i]).compare("backup",Qt::CaseInsensitive)==0)
|
||||
){
|
||||
continue;
|
||||
}
|
||||
|
||||
bool hasWindowEntry=false;
|
||||
QString comment = entries[i]->comment();
|
||||
int offset = 0;
|
||||
while ( (offset=lineMatch.indexIn(comment, offset))!=-1 ){
|
||||
QStringList captured = lineMatch.capturedTexts();
|
||||
offset += captured[0].length();
|
||||
int nr;
|
||||
QString entryWindow;
|
||||
bool valid;
|
||||
if (captured.size()==2){
|
||||
nr = 0;
|
||||
entryWindow = captured[1].trimmed().toLower();
|
||||
}
|
||||
else{
|
||||
nr = captured[1].toInt();
|
||||
entryWindow = captured[2].trimmed().toLower();
|
||||
}
|
||||
if (entryWindow.length()==0) continue;
|
||||
|
||||
hasWindowEntry = true;
|
||||
bool wildStart = (entryWindow[0]=='*');
|
||||
bool wildEnd = (entryWindow[entryWindow.size()-1]=='*');
|
||||
if (wildStart&&wildEnd){
|
||||
entryWindow.remove(0,1);
|
||||
if (entryWindow.length()!=0){
|
||||
entryWindow.remove(entryWindow.size()-1,1);
|
||||
valid = title.contains(entryWindow);
|
||||
}
|
||||
else
|
||||
valid = true;
|
||||
}
|
||||
else if (wildStart){
|
||||
entryWindow.remove(0,1);
|
||||
valid = title.endsWith(entryWindow);
|
||||
}
|
||||
else if (wildEnd){
|
||||
entryWindow.remove(entryWindow.size()-1,1);
|
||||
valid = title.startsWith(entryWindow);
|
||||
}
|
||||
else {
|
||||
valid = (title==entryWindow);
|
||||
}
|
||||
|
||||
if (valid){
|
||||
validEntries << entries[i];
|
||||
entryNumbers << nr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasWindowEntry && config->entryTitlesMatch()){
|
||||
QString entryTitle = entries[i]->title().toLower();
|
||||
if (!entryTitle.isEmpty() && title.contains(entryTitle)){
|
||||
validEntries << entries[i];
|
||||
entryNumbers << 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (validEntries.size()==1){
|
||||
QString err;
|
||||
perform(validEntries[0],err,wasLocked,entryNumbers[0],wasLocked);
|
||||
}
|
||||
else if (validEntries.size()>1){
|
||||
AutoTypeDlg* dlg = new AutoTypeDlg(validEntries, entryNumbers, wasLocked);
|
||||
dlg->show();
|
||||
}
|
||||
}
|
||||
|
||||
bool AutoType::registerGlobalShortcut(const Shortcut& s){
|
||||
if (s.key==shortcut.key && s.ctrl==shortcut.ctrl && s.shift==shortcut.shift && s.alt==shortcut.alt && s.altgr==shortcut.altgr && s.win==shortcut.win)
|
||||
return true;
|
||||
|
||||
Display* display = QX11Info::display();
|
||||
Window root = XRootWindow(display, MainWin->x11Info().screen());
|
||||
int code=XKeysymToKeycode(display, HelperX11::getKeysym(s.key));
|
||||
int mod=HelperX11::getShortcutModifierMask(s);
|
||||
|
||||
HelperX11::startCatchErrors();
|
||||
XGrabKey(display, code, mod, root, True, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(display, code, mod | Mod2Mask, root, True, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(display, code, mod | LockMask, root, True, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(display, code, mod | Mod2Mask | LockMask, root, True, GrabModeAsync, GrabModeAsync);
|
||||
HelperX11::stopCatchErrors();
|
||||
|
||||
if (HelperX11::errorOccurred()){
|
||||
XUngrabKey(display, code, mod, root);
|
||||
XUngrabKey(display, code, mod | Mod2Mask, root);
|
||||
XUngrabKey(display, code, mod | LockMask, root);
|
||||
XUngrabKey(display, code, mod | Mod2Mask | LockMask, root);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
unregisterGlobalShortcut();
|
||||
shortcut = s;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void AutoType::unregisterGlobalShortcut(){
|
||||
if (shortcut.key==0) return;
|
||||
|
||||
Display* display = QX11Info::display();
|
||||
Window root = XDefaultRootWindow(display);
|
||||
int code=XKeysymToKeycode(display, HelperX11::getKeysym(shortcut.key));
|
||||
int mod=HelperX11::getShortcutModifierMask(shortcut);
|
||||
|
||||
XUngrabKey(display, code, mod, root);
|
||||
XUngrabKey(display, code, mod | Mod2Mask, root);
|
||||
XUngrabKey(display, code, mod | LockMask, root);
|
||||
XUngrabKey(display, code, mod | Mod2Mask | LockMask, root);
|
||||
|
||||
shortcut.key = 0;
|
||||
}
|
||||
|
||||
#endif // GLOBAL_AUTOTYPE
|
||||
|
||||
AutoTypeAction::AutoTypeAction(AutoTypeActionType t, quint16 d) : type(t), data(d){
|
||||
}
|
||||
|
||||
|
||||
// AutoTypePrivate
|
||||
|
||||
void AutoTypePrivate::sleep(int msec){
|
||||
if (msec==0) return;
|
||||
timespec timeOut, remains;
|
||||
timeOut.tv_sec = msec/1000;
|
||||
timeOut.tv_nsec = (msec%1000)*1000000;
|
||||
nanosleep(&timeOut, &remains);
|
||||
}
|
||||
|
||||
void AutoTypePrivate::templateToKeysyms(const QString& tmpl, QList<AutoTypeAction>& keys,IEntryHandle* entry){
|
||||
//tmpl must be lower case!!!
|
||||
if(!tmpl.compare("title")){
|
||||
stringToKeysyms(entry->title(),keys);
|
||||
return;}
|
||||
if(!tmpl.compare("username")){
|
||||
stringToKeysyms(entry->username(),keys);
|
||||
return;}
|
||||
if(!tmpl.compare("url")){
|
||||
stringToKeysyms(entry->url(),keys);
|
||||
return;}
|
||||
if(!tmpl.compare("password")){
|
||||
SecString password=entry->password();
|
||||
password.unlock();
|
||||
stringToKeysyms(password,keys);
|
||||
return;
|
||||
}
|
||||
if(!tmpl.compare("space")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym(' '));
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("backspace") || !tmpl.compare("bs") || !tmpl.compare("bksp")){
|
||||
keys << AutoTypeAction(TypeKey, XK_BackSpace);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("break")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Break);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("capslock")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Caps_Lock);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("del") || !tmpl.compare("delete")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Delete);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("end")){
|
||||
keys << AutoTypeAction(TypeKey, XK_End);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("enter")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Return);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("esc")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Escape);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("help")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Help);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("home")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Home);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("insert") || !tmpl.compare("ins")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Insert);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("numlock")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Num_Lock);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("scroll")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Scroll_Lock);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("pgdn")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Page_Down);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("pgup")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Page_Up);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("prtsc")){
|
||||
keys << AutoTypeAction(TypeKey, XK_3270_PrintScreen);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("up")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Up);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("down")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Down);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("left")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Left);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("right")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Right);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("f1")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F1);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("f2")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F2);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("f3")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F3);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("f4")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F4);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("f5")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F5);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("f6")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F6);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("f7")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F7);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("f8")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F8);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("f9")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F9);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("f10")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F10);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("f11")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F11);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("f12")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F12);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("f13")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F13);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("f14")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F14);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("f15")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F15);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("f16")){
|
||||
keys << AutoTypeAction(TypeKey, XK_F16);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("add") || !tmpl.compare("plus")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('+'));
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("subtract")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('-'));
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("multiply")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('+'));
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("divide")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('/'));
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("at")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('@'));
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("percent")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('%'));
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("caret")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('^'));
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("tilde")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('~'));
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("leftbrace")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('{'));
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("rightbrace")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('}'));
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("leftparen")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('('));
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("rightparen")){
|
||||
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym(')'));
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("winl")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Super_L);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("winr")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Super_R);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("win")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Super_L);
|
||||
return;}
|
||||
|
||||
if(!tmpl.compare("tab")){
|
||||
keys << AutoTypeAction(TypeKey, XK_Tab);
|
||||
return;}
|
||||
|
||||
if(tmpl.startsWith("delay ") && tmpl.length()>6){
|
||||
bool ok;
|
||||
quint16 delay = tmpl.right(tmpl.length()-6).toInt(&ok);
|
||||
if (ok && delay>0 && delay<=10000)
|
||||
keys << AutoTypeAction(Delay, delay);
|
||||
}
|
||||
}
|
||||
|
||||
void AutoTypePrivate::stringToKeysyms(const QString& string,QList<AutoTypeAction>& KeySymList){
|
||||
for(int i=0; i<string.length();i++)
|
||||
KeySymList << AutoTypeAction(TypeKey, HelperX11::getKeysym(string[i]));
|
||||
}
|
||||
|
||||
QString AutoTypePrivate::getRootGroupName(IEntryHandle* entry){
|
||||
IGroupHandle* group = entry->group();
|
||||
int level = group->level();
|
||||
for (int i=0; i<level; i++)
|
||||
group = group->parent();
|
||||
|
||||
return group->title();
|
||||
}
|
|
@ -536,9 +536,12 @@ void KeepassEntryView::OnColumnMoved(int LogIndex,int OldVisIndex,int NewVisInde
|
|||
int KeepassEntryView::logicalColIndex(int LstIndex){
|
||||
int c=-1;
|
||||
for(int i=0;i<NUM_COLUMNS;i++){
|
||||
if(Columns.at(i))c++;
|
||||
if(i==10 && Columns.at(10) && ViewMode!=ShowSearchResults)c--;
|
||||
if(i==LstIndex)return c;
|
||||
if(Columns.at(i))
|
||||
c++;
|
||||
if(i==10 && Columns.at(10) && ViewMode!=ShowSearchResults)
|
||||
c--;
|
||||
if(i==LstIndex)
|
||||
return c;
|
||||
}
|
||||
Q_ASSERT(false);
|
||||
return -1;
|
||||
|
@ -578,15 +581,18 @@ void KeepassEntryView::resizeColumns(){
|
|||
int KeepassEntryView::columnListIndex(int LogicalIndex){
|
||||
int c=-1; int i;
|
||||
for(i=0;i<NUM_COLUMNS;i++){
|
||||
if(Columns.at(i))c++;
|
||||
if(i==10 && Columns.at(10) && ViewMode!=ShowSearchResults)c--;
|
||||
if(c==LogicalIndex)break;
|
||||
if(Columns.at(i))
|
||||
c++;
|
||||
if(i==10 && Columns.at(10) && ViewMode!=ShowSearchResults)
|
||||
c--;
|
||||
if(c==LogicalIndex)
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
void KeepassEntryView::OnColumnResized(int lindex,int Old, int New){
|
||||
void KeepassEntryView::OnColumnResized(int lindex, int Old, int New){
|
||||
if(!AutoResizeColumns)return;
|
||||
for(int i=0;i<header()->count();i++){
|
||||
ColumnSizes[columnListIndex(i)]=header()->sectionSize(i);
|
||||
|
@ -611,15 +617,20 @@ void KeepassEntryView::mouseMoveEvent(QMouseEvent *event){
|
|||
EntryViewItem* DragStartItem=(EntryViewItem*)itemAt(DragStartPos);
|
||||
if(!DragStartItem){
|
||||
while(selectedItems().size()){
|
||||
setItemSelected(selectedItems().first(),false);}
|
||||
setItemSelected(selectedItems().first(),false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(selectedItems().isEmpty()){
|
||||
setItemSelected(DragStartItem,true);}
|
||||
setItemSelected(DragStartItem,true);
|
||||
}
|
||||
else{
|
||||
bool AlreadySelected=false;
|
||||
for(int i=0;i<selectedItems().size();i++){
|
||||
if(selectedItems()[i]==DragStartItem){AlreadySelected=true; break;}
|
||||
if(selectedItems()[i]==DragStartItem){
|
||||
AlreadySelected=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!AlreadySelected){
|
||||
while(selectedItems().size()){
|
||||
|
@ -656,8 +667,7 @@ void KeepassEntryView::removeDragItems(){
|
|||
#ifdef AUTOTYPE
|
||||
void KeepassEntryView::OnAutoType(){
|
||||
if (selectedItems().size() == 0) return;
|
||||
QString error;
|
||||
AutoType::perform(((EntryViewItem*)selectedItems().first())->EntryHandle,error);
|
||||
autoType->perform(((EntryViewItem*)selectedItems().first())->EntryHandle);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ void KeepassGroupView::createItems(){
|
|||
void KeepassGroupView::updateIcons(){
|
||||
for(int i=0;i<Items.size();i++){
|
||||
Items[i]->setIcon(0,db->icon(Items[i]->GroupHandle->image()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KeepassGroupView::showSearchResults(){
|
||||
|
@ -86,7 +86,7 @@ void KeepassGroupView::addChildren(GroupViewItem* item){
|
|||
void KeepassGroupView::OnDeleteGroup(){
|
||||
if(config->askBeforeDelete()){
|
||||
if(QMessageBox::question(this,tr("Delete?"),
|
||||
tr("Are you sure you want to delete this group, all it's child groups and all their entries?"),
|
||||
tr("Are you sure you want to delete this group, all its child groups and all their entries?"),
|
||||
QMessageBox::Yes | QMessageBox::No,QMessageBox::No) == QMessageBox::No)
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -21,40 +21,6 @@
|
|||
#include "HelperX11.h"
|
||||
#include <QX11Info>
|
||||
|
||||
int HelperX11::getModifiers(Display *d,KeySym keysym, int keycode){
|
||||
int SymsPerKey;
|
||||
KeySym* Syms=XGetKeyboardMapping(d,keycode,1,&SymsPerKey);
|
||||
int c=-1;
|
||||
for(int i=0;i<4;i++)
|
||||
if(Syms[i]==keysym){
|
||||
c=i; break;
|
||||
}
|
||||
Q_ASSERT(c!=-1);
|
||||
XFree(Syms);
|
||||
return c;
|
||||
}
|
||||
|
||||
void HelperX11::pressModifiers(Display* d,int mods,bool press){
|
||||
switch(mods){
|
||||
case 0: //no modifier
|
||||
break;
|
||||
case 1: //Shift
|
||||
XTestFakeKeyEvent(d,XKeysymToKeycode(d,XK_Shift_L),press,2);
|
||||
break;
|
||||
case 2: //AltGr
|
||||
XTestFakeKeyEvent(d,XKeysymToKeycode(d,XK_ISO_Level3_Shift),press,2);
|
||||
break;
|
||||
case 3: //Shift+AltGr
|
||||
XTestFakeKeyEvent(d,XKeysymToKeycode(d,XK_Shift_L),press,2);
|
||||
XTestFakeKeyEvent(d,XKeysymToKeycode(d,XK_ISO_Level3_Shift),press,2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void HelperX11::releaseModifiers(Display* d,int mods){
|
||||
pressModifiers(d,mods,False);
|
||||
}
|
||||
|
||||
#ifdef GLOBAL_AUTOTYPE
|
||||
int HelperX11::getShortcutModifierMask(const Shortcut& s){
|
||||
int mod=0;
|
||||
|
@ -889,8 +855,8 @@ quint16 HelperX11::getKeysym(const QChar& c){
|
|||
|
||||
int MapSize = sizeof(KeysymMap) / sizeof(quint16) / 2;
|
||||
for (int i=0; i<MapSize; i++){
|
||||
if(unicode==KeysymMap[i][0])
|
||||
return KeysymMap[i][1];
|
||||
if (unicode==KeysymMap[i][1])
|
||||
return KeysymMap[i][0];
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -33,9 +33,6 @@
|
|||
|
||||
class HelperX11{
|
||||
public:
|
||||
static int getModifiers(Display *d,KeySym keysym, int keycode);
|
||||
static void pressModifiers(Display*,int mods,bool Press=true);
|
||||
static void releaseModifiers(Display*,int mods);
|
||||
static quint16 getKeysym(const QChar& c);
|
||||
#ifdef GLOBAL_AUTOTYPE
|
||||
static int getShortcutModifierMask(const Shortcut& s);
|
||||
|
|
|
@ -90,7 +90,7 @@ void ShortcutWidget::displayShortcut(quint32 key, bool release, bool ctrl, bool
|
|||
pShortcut.alt = alt;
|
||||
pShortcut.altgr = altgr;
|
||||
pShortcut.win = win;
|
||||
failed = AutoType::registerGlobalShortcut(pShortcut);
|
||||
failed = autoType->registerGlobalShortcut(pShortcut);
|
||||
if (!failed)
|
||||
setBackgroundColor(QColor(255, 150, 150));
|
||||
else
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
class IEntryHandle;
|
||||
|
||||
typedef enum tKeyType {PASSWORD=0,KEYFILE=1,BOTH=2};
|
||||
enum tKeyType {PASSWORD=0,KEYFILE=1,BOTH=2};
|
||||
struct Translation {
|
||||
QString nameCode;
|
||||
QString nameLong;
|
||||
|
|
12
src/main.cpp
12
src/main.cpp
|
@ -52,7 +52,7 @@ int main(int argc, char **argv)
|
|||
initAppPaths(argc,argv);
|
||||
CmdLineArgs args;
|
||||
if(!args.preparse(argc,argv)){ // searches only for the -cfg parameter
|
||||
qCritical(CSTR( args.error().append("\n") ));
|
||||
qCritical("%s", CSTR( args.error().append("\n") ));
|
||||
args.printHelp();
|
||||
return 1;
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ int main(int argc, char **argv)
|
|||
if(!plugin.load()){
|
||||
PluginLoadError=plugin.errorString();
|
||||
qWarning("Could not load desktop integration plugin:");
|
||||
qWarning(CSTR(PluginLoadError));
|
||||
qWarning("%s", CSTR(PluginLoadError));
|
||||
}
|
||||
else{
|
||||
QObject *plugininstance=plugin.instance();
|
||||
|
@ -128,7 +128,7 @@ int main(int argc, char **argv)
|
|||
#endif
|
||||
}
|
||||
if ( !args.parse(QApplication::arguments()) ){
|
||||
qCritical(CSTR( args.error().append("\n") ));
|
||||
qCritical("%s", CSTR( args.error().append("\n") ));
|
||||
args.printHelp();
|
||||
return 1;
|
||||
}
|
||||
|
@ -151,9 +151,7 @@ int main(int argc, char **argv)
|
|||
|
||||
QApplication::setQuitOnLastWindowClosed(false);
|
||||
KeepassMainWindow *mainWin = new KeepassMainWindow(args.file(), args.startMinimized(), args.startLocked());
|
||||
#ifdef GLOBAL_AUTOTYPE
|
||||
AutoType::init();
|
||||
#endif
|
||||
|
||||
int r=app->exec();
|
||||
delete mainWin;
|
||||
delete eventListener;
|
||||
|
@ -255,7 +253,7 @@ QString findPlugin(const QString& filename){
|
|||
bool EventListener::eventFilter(QObject*, QEvent* event){
|
||||
if (!EventOccurred){
|
||||
int t = event->type();
|
||||
if ( t>=QEvent::MouseButtonPress&&t<=QEvent::KeyRelease || t>=QEvent::HoverEnter&&t<=QEvent::HoverMove )
|
||||
if ( (t>=QEvent::MouseButtonPress && t<=QEvent::KeyRelease) || (t>=QEvent::HoverEnter && t<=QEvent::HoverMove) )
|
||||
EventOccurred = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -61,10 +61,10 @@ KeepassMainWindow::KeepassMainWindow(const QString& ArgFile,bool ArgMin,bool Arg
|
|||
setUnifiedTitleAndToolBarOnMac(true);
|
||||
#endif
|
||||
#ifdef AUTOTYPE
|
||||
AutoType::MainWin=this;
|
||||
initAutoType(this);
|
||||
#endif
|
||||
#ifdef GLOBAL_AUTOTYPE
|
||||
AutoType::registerGlobalShortcut(config->globalShortcut());
|
||||
autoType->registerGlobalShortcut(config->globalShortcut());
|
||||
#endif
|
||||
setWindowModified(false);
|
||||
setGeometry(config->mainWindowGeometry(geometry()));
|
||||
|
@ -1016,7 +1016,7 @@ void KeepassMainWindow::closeEvent(QCloseEvent* e){
|
|||
}
|
||||
|
||||
#ifdef GLOBAL_AUTOTYPE
|
||||
AutoType::unregisterGlobalShortcut();
|
||||
autoType->unregisterGlobalShortcut();
|
||||
#endif
|
||||
|
||||
config->setMainWindowGeometry(geometry());
|
||||
|
|
10
src/src.pro
10
src/src.pro
|
@ -45,12 +45,12 @@ unix : !macx : !isEqual(QMAKE_WIN32,1){
|
|||
INSTALLS += share
|
||||
contains(DEFINES,AUTOTYPE){
|
||||
LIBS += -lXtst
|
||||
SOURCES += lib/HelperX11.cpp lib/AutoType_X11.cpp
|
||||
HEADERS += lib/HelperX11.h
|
||||
SOURCES += lib/HelperX11.cpp lib/AutoTypeX11.cpp
|
||||
HEADERS += lib/HelperX11.h lib/AutoTypeX11.h
|
||||
}
|
||||
contains(DEFINES,GLOBAL_AUTOTYPE){
|
||||
SOURCES += Application_X11.cpp
|
||||
HEADERS += Application_X11.h
|
||||
SOURCES += Application_X11.cpp lib/AutoTypeGlobalX11.cpp
|
||||
HEADERS += Application_X11.h lib/AutoTypeGlobalX11.h
|
||||
}
|
||||
SOURCES += main_unix.cpp
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ macx {
|
|||
#-------------------------------------------------------------------------------
|
||||
isEqual(QMAKE_WIN32,1){
|
||||
CONFIG += windows
|
||||
isEmpty(PREFIX): PREFIX = "C:/Program files/KeePassX"
|
||||
isEmpty(PREFIX): PREFIX = "C:/Program\ files/KeePassX"
|
||||
TARGET = ../bin/KeePassX
|
||||
target.path = $${PREFIX}
|
||||
data.files += ../share/keepassx/*
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue