Skip to content
This repository has been archived by the owner on Dec 17, 2017. It is now read-only.

Commit

Permalink
Simple alt-tab app switcher for WMs where it is not supported. Initia…
Browse files Browse the repository at this point in the history
…l import.
  • Loading branch information
pvanek committed Jan 28, 2011
1 parent c7ccd51 commit 9cec345
Show file tree
Hide file tree
Showing 15 changed files with 1,409 additions and 7 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Expand Up @@ -24,6 +24,7 @@ add_subdirectory( librazorqt )
add_subdirectory( razorqt-session )
add_subdirectory( razorqt-panel )
add_subdirectory( razorqt-desktop )
add_subdirectory( razorqt-appswitcher )
add_subdirectory( razorqt-resources )


Expand Down
10 changes: 5 additions & 5 deletions librazorqt/razorqt/xfitman.cpp
Expand Up @@ -62,9 +62,9 @@ Window XfitMan::getActiveAppWindow()
// qDebug() << "Getting active Window";
Window focuswin = getActiveWindow();
// qDebug() << focuswin;
QList<Window>* clientList = getClientlist();
QList<Window> clientList = getClientList();
//while ((getName(focuswin) == "BLAH!" || !clientList.keys().contains(focuswin) ) && (focuswin != root) )
while ((getName(focuswin) == "BLAH!" || !clientList->contains(focuswin) ) && (focuswin != root))
while ((getName(focuswin) == "BLAH!" || !clientList.contains(focuswin) ) && (focuswin != root))
{

runs ++;
Expand Down Expand Up @@ -352,7 +352,7 @@ bool XfitMan::acceptWindow(Window _wid)
/**
* @brief gets a client list
*/
QList<Window>* XfitMan::getClientlist()
QList<Window> XfitMan::getClientList()
{
//initialize the parameters for the XGetWindowProperty call
int format;
Expand All @@ -364,14 +364,14 @@ QList<Window>* XfitMan::getClientlist()
*/


QList<Window>* output = new QList<Window>;
QList<Window> output;

XGetWindowProperty(QX11Info::display(),root,atomMap["net_client_list"],0, 4096, FALSE, AnyPropertyType,
&type, &format, &length, &rest,(unsigned char**) &data);


for (unsigned int i = 0; i < length; i ++)
output->append(data[i]);
output.append(data[i]);


XFree(data);
Expand Down
4 changes: 2 additions & 2 deletions librazorqt/razorqt/xfitman.h
Expand Up @@ -31,7 +31,7 @@ class XfitMan
void setStrut(Window _wid, int _height);
void unsetStrut(Window _wid);
void getAtoms();
QList<Window>* getClientlist();
QList<Window> getClientList();
bool getClientIcon(Window _wid, QPixmap& _pixreturn);
void setEventRoute();
void setClientStateFlag(Window _wid, QString _atomcode, int _action);
Expand All @@ -41,7 +41,7 @@ class XfitMan
void moveWindowtoDesktop(Window _wid, int _display);
void raiseWindow(Window _wid);
void resizeWindow(Window _wid, int _height, int _width);

void setActiveDesktop(int _desktop);
void mapRaised(Window _wid)
{
Expand Down
42 changes: 42 additions & 0 deletions razorqt-appswitcher/CMakeLists.txt
@@ -0,0 +1,42 @@
project( razor-desktop )
cmake_minimum_required( VERSION 2.6 )

if (NOT CMAKE_BUILD_TYPE)
set ( CMAKE_BUILD_TYPE Release )
endif (NOT CMAKE_BUILD_TYPE)

add_definitions ( -Wall )
find_package ( Qt4 REQUIRED )
find_package ( X11 REQUIRED )
include ( ${QT_USE_FILE} )
include_directories (
${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}
${QT_QTCORE_INCLUDE_DIR} ${QT_QTGUI_INCLUDE_DIR} ${QT_QTXML_INCLUDE_DIR} ${QT_QTDBUS_INCLUDE_DIR}
${X11_INCLUDE_DIR}
${CMAKE_SOURCE_DIR}/librazorqt/
src
src/qxt)

set ( razor-appswitcher_HDRS
src/appswitcher.h
src/qxt/qxtglobal.h
src/qxt/qxtglobalshortcut.h
src/qxt/qxtglobalshortcut_p.h
)

set ( razor-appswitcher_SRCS
src/main.cpp
src/appswitcher.cpp
src/qxt/qxtglobal.cpp
src/qxt/qxtglobalshortcut.cpp
src/qxt/qxtglobalshortcut_x11.cpp
)

QT4_WRAP_CPP(MOCS ${razor-appswitcher_HDRS})
QT4_WRAP_UI(UIS src/appswitcher.ui)

SET (exec razor-appswitcher)

add_executable ( ${exec} ${razor-appswitcher_SRCS} ${UIS} ${RSCS} ${TRS} ${MOCS} )
target_link_libraries ( ${exec} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTXML_LIBRARY} ${QT_QTDBUS_LIBRARY} ${X11_X11_LIB} ${CMAKE_BINARY_DIR}/librazorqt/librazorqt.so)
INSTALL(TARGETS ${exec} RUNTIME DESTINATION bin)
209 changes: 209 additions & 0 deletions razorqt-appswitcher/src/appswitcher.cpp
@@ -0,0 +1,209 @@
#include "appswitcher.h"
#include "qxtglobalshortcut.h"

#include <QMessageBox>
#include <QEvent>



RazorAppSwitcher::AppSwitcher::AppSwitcher()
: QWidget(0, Qt::FramelessWindowHint | Qt::Tool)
{
setupUi(this);
installEventFilter(this);

m_layout = new QHBoxLayout();
QWidget * background = new QWidget(this);
scrollArea->setWidget(background);
background->setLayout(m_layout);

m_x = new XfitMan();
Q_ASSERT(m_x);

m_key = new QxtGlobalShortcut(this);

//QKeySequence ks(Qt::CTRL + Qt::ALT + Qt::Key_T);
QKeySequence ks(Qt::ALT + Qt::Key_Tab);
if (! m_key->setShortcut(ks))
{
QMessageBox::information(this, tr("Global keyboard shortcut"),
tr("Global shorcut: '%1' cannot be registered").arg(ks.toString()));
qApp->exit(1);
}

m_localKey = new QShortcut(ks, this, SLOT(selectNextItem()), SLOT(selectNextItem()));

connect(m_key, SIGNAL(activated()), this, SLOT(handleApps()));
}

void RazorAppSwitcher::AppSwitcher::handleApps()
{
qDebug() << "AppSwitcher::handleApps() start";
if (!isVisible())
{
QRect desktop = QApplication::desktop()->availableGeometry(m_x->getActiveDesktop());
int x, y;
x = desktop.width()/2 - width() / 2;
y = desktop.height()/2 - height() / 2;
move(x, y);
qDebug() << "PARENT" << parent() << desktop << x << y;
show();
}

if (m_layout->count())
{
QLayoutItem * item;
while ((item = m_layout->takeAt(0)) != 0)
{
qDebug() << "Cleaning layout" << item;
item->widget()->hide();
delete item;
}
}
m_list.clear();

QList<Window> l = m_x->getClientList();
Window actWin = m_x->getActiveWindow();
bool setImplicitFocus = true;
// setup new windows
foreach (Window w, l)
{
if (!m_x->acceptWindow(w))
{
qDebug() << "Skipped due props:" << m_x->getName(w);
continue;
}
qDebug() << "Append to layout:" << w << m_x->getName(w);
QPixmap pm;
if (! m_x->getClientIcon(w, pm))
qDebug() << "No icon for:" << w << m_x->getName(w);

SwitcherItem * item = new SwitcherItem(w, m_x->getName(w), pm, this);
connect(item, SIGNAL(infoChanged(const QString&)),
infoLabel, SLOT(setText(const QString&)));
m_list.append(item);
m_layout->addWidget(item);

if (w == actWin)
{
item->setFocus(Qt::OtherFocusReason);
setImplicitFocus = false;
}
}

if (setImplicitFocus)
selectNextItem();
}

void RazorAppSwitcher::AppSwitcher::hideEvent(QHideEvent *e)
{
m_key->blockSignals(false);
QWidget::hideEvent(e);
}

void RazorAppSwitcher::AppSwitcher::showEvent(QShowEvent *e)
{
m_key->blockSignals(true);
QWidget::showEvent(e);
}

void RazorAppSwitcher::AppSwitcher::keyPressEvent(QKeyEvent * e)
{
qDebug() << "AppSwitcher::keyPressEvent" << e << e->key() << e->modifiers();;
switch (e->key())
{
case Qt::Key_Escape:
close();
break;
case Qt::Key_Enter:
case Qt::Key_Return:
{
SwitcherItem * item = qobject_cast<SwitcherItem*>(QApplication::focusWidget());
if (! item)
{
qDebug() << "AppSwitcher::keyPressEvent activation. Something is wrong - focus widget is not on SwitcherItem!";
return;
}
m_x->raiseWindow(item->window());
close();
break;
}
};

QWidget::keyPressEvent(e);
}

//void RazorAppSwitcher::AppSwitcher::keyReleaseEvent(QKeyEvent * e)
//{
// qDebug() << "AppSwitcher::keyReleaseEvent" << e << e->key() << e->modifiers();;
// QWidget::keyReleaseEvent(e);
//}

bool RazorAppSwitcher::AppSwitcher::eventFilter(QObject * o, QEvent * e)
{
//qDebug() << "AppSwitcher::eventFilter" << e;
if (e->type() == QEvent::WindowDeactivate)
{
close();
return true;
}
return QWidget::eventFilter(o, e);
}

void RazorAppSwitcher::AppSwitcher::selectNextItem()
{
if (m_list.count() == 0)
{
qDebug() << "AppSwitcher::selectItem m_list is empty. No action";
return;
}

SwitcherItem * item = qobject_cast<SwitcherItem*>(QApplication::focusWidget());
if (! item)
{
qDebug() << "AppSwitcher::selectItem implicit item (0) ";
item = m_list.at(0);
}
else
{
qDebug() << "AppSwitcher::selectItem selected" << item << item->text();
int index = m_list.indexOf(item);
if (index == -1)
{
qDebug() << "AppSwitcher::selectItem item not found in list. And it's wrong!" << item << item->text();
index = 0;
}
++index;
if (index > m_list.count() - 1)
index = 0;
item = m_list.at(index);
}

//infoLabel->setText(item->text());
item->setFocus(Qt::OtherFocusReason);
}


RazorAppSwitcher::SwitcherItem::SwitcherItem(Window window, const QString & text, const QPixmap & pixmap, QWidget * parent)
: QToolButton(parent),
m_window(window)
{
setObjectName("SwitcherItem '" + text + "'");
setFocusPolicy(Qt::WheelFocus);
setFocusProxy(0);
setMaximumSize(64, 64);
setMinimumSize(64, 64);
setToolButtonStyle(Qt::ToolButtonIconOnly);
setIconSize(QSize(60, 60));
setToolTip(text);

setIcon(pixmap);
setText(text);
}

void RazorAppSwitcher::SwitcherItem::focusInEvent(QFocusEvent * e)
{
qDebug() << "SwitcherItem::focusInEvent" << e;
emit infoChanged(text());
QToolButton::focusInEvent(e);
}

0 comments on commit 9cec345

Please sign in to comment.