Trembles the weave as the clock ticks, attain another microstate.

Every disorder causes every duration, which ensures the one that stays.
reality is relative. natural is disorder.
[R]obinhood[P]andey

Merging scripting from
^/branches/work/kwin_scripting TO
^/trunk

svn path=/trunk/KDE/kdebase/workspace/; revision=1177865
icc-effect-5.14.5
Rohan Ramdas Prabhu 2010-09-21 14:31:40 +00:00
parent bb60cd51ce
commit 2aec750ebf
31 changed files with 4236 additions and 18 deletions

View File

@ -112,6 +112,18 @@ set(kwin_KDEINIT_SRCS
tilinglayout.cpp
tilinglayoutfactory.cpp
#load the scripting related functions
scripting/scripting.cpp
scripting/workspace.cpp
scripting/client.cpp
scripting/meta.cpp
scripting/toplevel.cpp
scripting/windowinfo.cpp
scripting/s_clientgroup.cpp
scripting/workspaceproxy.cpp
scripting/chelate.cpp
scripting/timer.cpp
# tiling layouts
# spiral
#tilinglayouts/spiral/spiralfactory.cpp

View File

@ -29,6 +29,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "client.h"
#include "workspace.h"
#include "scripting/client.h"
#include <fixx11h.h>
#include <kxerrorhandler.h>
#include <kstartupinfo.h>
@ -226,6 +228,12 @@ void Workspace::setActiveClient( Client* c, allowed_t )
{
if ( active_client == c )
return;
if(c != 0) {
emit clientActivated(c);
c->sl_activated();
}
if( active_popup && active_popup_client != c && set_active_client_recursion == 0 )
closeActivePopup();
StackingUpdatesBlocker blocker( this );

View File

@ -33,6 +33,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdlib.h>
#include <signal.h>
#include "scripting/client.h"
#include "scripting/scripting.h"
#include "scripting/workspaceproxy.h"
#include "bridge.h"
#include "group.h"
#include "workspace.h"
@ -125,6 +129,8 @@ Client::Client( Workspace* ws )
, paintRedirector( 0 )
, electricMaximizing( false )
{ // TODO: Do all as initialization
scriptCache = new QHash<QScriptEngine*, ClientResolution>();
// Set the initial mapping state
mapping_state = Withdrawn;
@ -172,6 +178,9 @@ Client::Client( Workspace* ws )
maxmode_restore = MaximizeRestore;
cmap = None;
//Client to workspace connections require that each
//client constructed be connected to the workspace wrapper
// TabBoxClient
m_tabBoxClient = new TabBox::TabBoxClientImpl();
@ -191,6 +200,7 @@ Client::Client( Workspace* ws )
*/
Client::~Client()
{
//SWrapper::Client::clientRelease(this);
#ifdef HAVE_XSYNC
if( sync_alarm != None )
XSyncDestroyAlarm( display(), sync_alarm );
@ -204,6 +214,7 @@ Client::~Client()
assert( !check_active_modal );
delete bridge;
delete m_tabBoxClient;
delete scriptCache;
}
// Use destroyClient() or releaseWindow(), Client instances cannot be deleted directly
@ -211,7 +222,7 @@ void Client::deleteClient( Client* c, allowed_t )
{
delete c;
}
/**
* Releases the window. The client has done its job and the window is still existing.
*/
@ -882,6 +893,16 @@ void Client::minimize( bool avoid_animation )
{
if( !isMinimizable() || isMinimized() )
return;
//Scripting call. Does not use a signal/slot mechanism
//as ensuring connections was a bit difficult between
//so many clients and the workspace
SWrapper::WorkspaceProxy* ws_wrap = SWrapper::WorkspaceProxy::instance();
if(ws_wrap != 0) {
ws_wrap->sl_clientMinimized(this);
}
emit s_minimized();
Notify::raise( Notify::Minimize );
@ -907,6 +928,13 @@ void Client::unminimize( bool avoid_animation )
{
if( !isMinimized())
return;
SWrapper::WorkspaceProxy* ws_wrap = SWrapper::WorkspaceProxy::instance();
if(ws_wrap != 0) {
ws_wrap->sl_clientUnminimized(this);
}
emit s_unminimized();
Notify::raise( Notify::UnMinimize );
minimized = false;
@ -1641,7 +1669,7 @@ void Client::takeFocus( allowed_t )
{
#ifndef NDEBUG
static Time previous_focus_timestamp;
static Client* previous_client;
// static Client* previous_client;
//if( previous_focus_timestamp == xTime() && previous_client != this )
// {
@ -1850,6 +1878,10 @@ void Client::getWMHints()
updateAllowedActions(); // Group affects isMinimizable()
}
void Client::sl_activated() {
emit s_activated();
}
void Client::getMotifHints()
{
bool mgot_noborder, mnoborder, mresize, mmove, mminimize, mmaximize, mclose;

View File

@ -35,6 +35,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <X11/Xutil.h>
#include <fixx11h.h>
#include <QScriptValue>
#include "scripting/client.h"
#include "utils.h"
#include "options.h"
#include "workspace.h"
@ -53,6 +56,12 @@ class QProcess;
class QTimer;
class KStartupInfoData;
namespace SWrapper {
class Client;
}
typedef QPair<SWrapper::Client*, QScriptValue> ClientResolution;
namespace KWin
{
namespace TabBox {
@ -105,6 +114,13 @@ class Client
*/
bool isSpecialWindow() const;
bool hasNETSupport() const;
/**
* This is a public object with no wrappers or anything to keep it fast,
* so in essence, direct access is allowed. Please be very careful while
* using this object
*/
QHash<QScriptEngine*, ClientResolution>* scriptCache;
QSize minSize() const;
QSize maxSize() const;
@ -225,13 +241,13 @@ class Client
void updateShape();
void setGeometry( int x, int y, int w, int h, ForceGeometry_t force = NormalGeometrySet );
void setGeometry( const QRect& r, ForceGeometry_t force = NormalGeometrySet );
void setGeometry( int x, int y, int w, int h, ForceGeometry_t force = NormalGeometrySet, bool emitJs = true );
void setGeometry( const QRect& r, ForceGeometry_t force = NormalGeometrySet, bool emitJs = true );
void move( int x, int y, ForceGeometry_t force = NormalGeometrySet );
void move( const QPoint& p, ForceGeometry_t force = NormalGeometrySet );
/// plainResize() simply resizes
void plainResize( int w, int h, ForceGeometry_t force = NormalGeometrySet );
void plainResize( const QSize& s, ForceGeometry_t force = NormalGeometrySet );
void plainResize( int w, int h, ForceGeometry_t force = NormalGeometrySet, bool emitJs = true );
void plainResize( const QSize& s, ForceGeometry_t force = NormalGeometrySet, bool emitJs = true );
/// resizeWithChecks() resizes according to gravity, and checks workarea position
void resizeWithChecks( int w, int h, ForceGeometry_t force = NormalGeometrySet );
void resizeWithChecks( const QSize& s, ForceGeometry_t force = NormalGeometrySet );
@ -440,7 +456,25 @@ class Client
void syncTimeout();
void delayedSetShortcut();
void repaintDecorationPending();
//Signals for the scripting interface
//Signals make an excellent way for communcation
//in between objects as compared to simple function
//calls
signals:
void s_clientMoved();
void clientManaging(KWin::Client*);
void s_minimized();
void s_unminimized();
void maximizeSet(QPair<bool, bool>);
void s_activated();
void s_fullScreenSet(bool, bool);
// To make workspace-client calls, a few slots are also
// required
public slots:
void sl_activated();
private:
void exportMappingState( int s ); // ICCCM 4.1.3.1, 4.1.4, NETWM 2.5.1
bool isManaged() const; ///< Returns false if this client is not yet managed
@ -656,6 +690,7 @@ class Client
ElectricMaximizingMode electricMode;
friend bool performTransiencyCheck();
friend class SWrapper::Client;
};
/**
@ -896,9 +931,9 @@ inline QRect Client::visibleRect() const
return geometry().adjusted( -padding_left, -padding_top, padding_right, padding_bottom );
}
inline void Client::setGeometry( const QRect& r, ForceGeometry_t force )
inline void Client::setGeometry( const QRect& r, ForceGeometry_t force, bool emitJs )
{
setGeometry( r.x(), r.y(), r.width(), r.height(), force );
setGeometry( r.x(), r.y(), r.width(), r.height(), force, emitJs );
}
inline void Client::move( const QPoint& p, ForceGeometry_t force )
@ -906,9 +941,9 @@ inline void Client::move( const QPoint& p, ForceGeometry_t force )
move( p.x(), p.y(), force );
}
inline void Client::plainResize( const QSize& s, ForceGeometry_t force )
inline void Client::plainResize( const QSize& s, ForceGeometry_t force, bool emitJs )
{
plainResize( s.width(), s.height(), force );
plainResize( s.width(), s.height(), force, emitJs );
}
inline void Client::resizeWithChecks( const QSize& s, ForceGeometry_t force )

View File

@ -22,6 +22,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef KWIN_CLIENTGROUP_H
#define KWIN_CLIENTGROUP_H
#include <QObject>
#include "kdecoration.h"
#include "utils.h"
@ -41,12 +43,15 @@ class Client;
* copies of the same client. A client MUST NOT be in two groups at the same
* time. All decorated clients SHOULD be in a group, even if it's a group of
* one client.
*
* rohanp: Had to convert this object to a QObject to make it easier for adding
* scripting interface to ClientGroup.
*
* If a group contains multiple clients then only one will ever be mapped at
* any given time.
*/
class ClientGroup
{
class ClientGroup : public QObject {
Q_OBJECT
public:
/**
* Creates a new group containing \p c.

View File

@ -30,6 +30,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "client.h"
#include "workspace.h"
#include "scripting/workspaceproxy.h"
#include <kapplication.h>
#include <kglobal.h>
#include <kwindowsystem.h>
@ -1947,7 +1949,7 @@ bool Client::isMaximizable() const
/*!
Reimplemented to inform the client about the new window position.
*/
void Client::setGeometry( int x, int y, int w, int h, ForceGeometry_t force )
void Client::setGeometry( int x, int y, int w, int h, ForceGeometry_t force, bool emitJs )
{
// this code is also duplicated in Client::plainResize()
// Ok, the shading geometry stuff. Generally, code doesn't care about shaded geometry,
@ -1959,7 +1961,8 @@ void Client::setGeometry( int x, int y, int w, int h, ForceGeometry_t force )
// This gets more complicated in the case the code does only something like
// setGeometry( geometry()) - geometry() will return the shaded frame geometry.
// Such code is wrong and should be changed to handle the case when the window is shaded,
// for example using Client::clientSize().
// for example using Client::clientSize()
if( shade_geometry_change )
; // nothing
else if( isShade())
@ -2046,9 +2049,15 @@ void Client::setGeometry( int x, int y, int w, int h, ForceGeometry_t force )
// Update states of all other windows in this group
if( clientGroup() )
clientGroup()->updateStates( this );
if(emitJs == true)
{
emit s_clientMoved();
}
}
void Client::plainResize( int w, int h, ForceGeometry_t force )
void Client::plainResize( int w, int h, ForceGeometry_t force, bool emitJs )
{
// this code is also duplicated in Client::setGeometry(), and it's also commented there
if( shade_geometry_change )
@ -2102,6 +2111,11 @@ void Client::plainResize( int w, int h, ForceGeometry_t force )
XMoveResizeWindow( display(), window(), 0, 0, cs.width(), cs.height());
}
updateShape();
if(emitJs == true) {
emit s_clientMoved();
}
sendSyntheticConfigureNotify();
updateWindowRules();
checkMaximizeGeometry();
@ -2204,6 +2218,16 @@ void Client::maximize( MaximizeMode m )
*/
void Client::setMaximize( bool vertically, bool horizontally )
{
//Scripting call. Does not use a signal/slot mechanism
//as ensuring connections was a bit difficult between
//so many clients and the workspace
SWrapper::WorkspaceProxy* ws_wrap = SWrapper::WorkspaceProxy::instance();
if(ws_wrap != 0) {
ws_wrap->sl_clientMaximizeSet(this, QPair<bool, bool>(vertically, horizontally));
}
emit maximizeSet(QPair<bool, bool>(vertically, horizontally));
// changeMaximize() flips the state, so change from set->flip
changeMaximize(
max_mode & MaximizeVertical ? !vertically : vertically,
@ -2551,6 +2575,13 @@ void Client::setFullScreen( bool set, bool user )
}
updateWindowRules();
workspace()->checkUnredirect();
SWrapper::WorkspaceProxy* ws_object = SWrapper::WorkspaceProxy::instance();
if(ws_object != 0) {
ws_object->sl_clientFullScreenSet(this, set, user);
}
emit s_fullScreenSet(set, user);
}

View File

@ -40,6 +40,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <kdefakes.h>
#include <QtDBus/QtDBus>
#include <stdlib.h>
#include <QMessageBox>
#include <QEvent>
#include "scripting/scripting.h"
#include <kdialog.h>
#include <kstandarddirs.h>
#include <kdebug.h>
@ -489,8 +493,9 @@ KDE_EXPORT int kdemain( int argc, char * argv[] )
args.add( "lock", ki18n( "Disable configuration options" ));
args.add( "replace", ki18n( "Replace already-running ICCCM2.0-compliant window manager" ));
args.add( "crashes <n>", ki18n( "Indicate that KWin has recently crashed n times" ));
args.add( "noscript", ki18n( "Load the script testing dialog" ));
KCmdLineArgs::addCmdLineOptions( args );
if( KDE_signal( SIGTERM, KWin::sighandler ) == SIG_IGN )
KDE_signal( SIGTERM, SIG_IGN );
if( KDE_signal( SIGINT, KWin::sighandler ) == SIG_IGN )
@ -508,6 +513,8 @@ KDE_EXPORT int kdemain( int argc, char * argv[] )
org::kde::KSMServerInterface ksmserver( "org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus());
ksmserver.suspendStartup( "kwin" );
KWin::Application a;
KWin::Scripting scripting;
ksmserver.resumeStartup( "kwin" );
KWin::SessionManager weAreIndeed;
KWin::SessionSaveDoneHelper helper;
@ -528,6 +535,9 @@ KDE_EXPORT int kdemain( int argc, char * argv[] )
QDBusConnection::sessionBus().interface()->registerService(
appname, QDBusConnectionInterface::DontQueueService );
KCmdLineArgs* sargs = KCmdLineArgs::parsedArgs();
scripting.start();
return a.exec();
}

View File

@ -32,6 +32,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "rules.h"
#include "group.h"
#include "scripting/workspaceproxy.h"
namespace KWin
{
@ -43,6 +45,14 @@ namespace KWin
bool Client::manage( Window w, bool isMapped )
{
StackingUpdatesBlocker stacking_blocker( workspace() );
//Scripting call. Does not use a signal/slot mechanism
//as ensuring connections was a bit difficult between
//so many clients and the workspace
SWrapper::WorkspaceProxy* ws_wrap = SWrapper::WorkspaceProxy::instance();
if(ws_wrap != 0) {
ws_wrap->sl_clientManaging(this);
}
grabXServer();

211
scripting/IMPLIST Normal file
View File

@ -0,0 +1,211 @@
# This is a list of all the events and methods that are currently
# supported methods and events. Please follow the format given
# below for adding new methods/events
#
# TYPE OBJECT NAME SIGNAL WRAPPERSLOT WRAPPERSIGNAL
# For properties:
# GO: GET only | SG: SET and GET functions defined
#
OBJECTS_DOC_LIST_START
Instantiable objects:
---------------------
(instantiable) ClientGroup : Create a group which corresponds to a ClientGroup and add/remove/introspect tabs of the group.
(instantiable) QTimer : A QTimer class for creating polling or one shot timers. Linked from plasma.
Others
------
(floating) client : Client objects which correspond to an actual KWin::Client.
(singleton) workspace : The main KWin::Workspace object.
(singleton) config : Configuration parameters for the running script.
(floating) toplevel : Inherited by client. Corresponds to a KWin::Toplevel or any of it's derived classes.
OBJECTS_DOC_LIST_END
PROPERTIES_DOC_LIST_START
Implemented properties:
--------------------
method workspace getAllClients NONE NONE NONE
event workspace currentDesktopChanged currentDesktopChanged sl_currentDesktopChanged currentDesktopChanged
event workspace desktopPresenceChanged desktopPresenceChanged sl_desktopPresenceChanged desktopPresenceChanged
method client caption NONE NONE NONE
event client clientMoved clientMoved sl_clientMoved clientMoved
method client close NONE NONe NONE
property workspace currentDesktop (GO) NONE NONE NONE
event workspace clientAdded clientAdded sl_clientAdded clientAdded
event workspace clientManaging DIRECT_FUNCTION_CALL sl_clientManaging clientManaging
event workspace clientMinimized DIRECT_FUNCTION_CALL sl_clientMinimized clientMinimized
event workspace clientMaximizeSet DIRECT_FUNCTION_CALL sl_clientMaximizeSet clientMaximizeSet
event workspace killWindowCalled DIRECT_FUNCTION_CALL sl_killWindowCalled killWindowCalled
event client minimized s_minimized DIRECT_CONNECTION minimized
event client maximizeSet maximizeSet sl_maximizeSet maximizeSet
method toplevel x NONE NONE NONE
method toplevel y NONE NONE NONE
method toplevel width NONE NONE NONE
method toplevel height NONE NONE NONE
method toplevel size NONE NONE NONE
metho toplevel pos NONE NONE NONE
event client activated s_activated DIRECT_CONNECTION gotFocus
event workspace clientActivated clientActivated sl_clientActivated clientActivated
method toplevel geometry NONE NONE NONE
method client move NONE NONE NONE
method client resize NONE NONE NONE
method client setGeometry NONE NONE NONE
method client getWindowInfo NONE NONE NONE
property windowinfo isValid (GO) NONE NONE NONE
property windowinfo visibleName (GO) NONE NONE NONE
property windowinfo isMinimized (GO) NONE NONE NONE
property windowinfo state (GO) NONE NONE NONE
method client isTransient NONE NONE NONE
method client transientFor NONE NONE NONE
method client activate NONE NONE NONE
method client setCaption NONE NONE NONE
method workspace dimensions NONE NONE NONE
method workspace desktopGridSize NONE NONE NONE
method client isFullScreen NONE NONE NONE
method client isFullScreenable NONE NONE NONE
method client setFullScreen NONE NONE NONE
event client fullScreenSet s_fullScreenSet DIRECT_CONNECTION fullScreenSet
event workspace clientFullScreenSet DIRECT_FUNCTION_CALL sl_clientFullScreenSet clientFullScreenSet
method toplevel opacity NONE NONE NONE
method toplevel hasAlpha NONE NONE NONE
method toplevel setOpacity NONE NONE NONE
method clientgroup clientgroup (ctor) NONE NONE NONE
method clientgroup add NONE NONE NONE
method workspace activeClient NONE NONE NONE
method workspace clientGroups NONE NONE NONE
method clientgroup remove NONE NONE NONE
method clientgroup clients NONE NONE NONE
method client unminimize NONE NONE NONE
method client restore NONE NONE NONE
event workspace clientUnminimized DIRECT_FUNCTION_CALL sl_clientUnminimized clientUnminimized
event workspace clientRestored DIRECT_FUNCTION_CALL sl_clientUnminimized clientRestored
event client unminimized s_unminimized sl_unminimized unminimized
event client restored s_unminimized sl_unminimized restored
method client clientGroup NONE NONE NONE
method clientgroup contains NONE NONE NONE
method clientgroup indexOf NONE NONE NONE
method clientgroup move NONE NONE NONE
method clientgroup removeAll NONE NONE NONE
method clientgroup closeAll NONE NONE NONE
method clientgroup minSize NONE NONE NONE
method clientgroup maxSize NONE NONE NONE
property windowinfo windowRole (GO) NONE NONE NONE
property windowinfo windowClassClass (GO) NONE NONE NONE
property windowinfo windowClassName (GO) NONE NONE NONE
property config loaded (GO) NONE NONE NONE
method config exists NONE NONE NONE
method config get NONE NONE NONE
method client desktop NONE NONE NONE
method client isShade NONE NONE NONE
method client isShadeable NONE NONE NONE
method client isMinimized NONE NONE NONE
method client isMinimizable NONE NONE NONE
method client isMaximizable NONE NONE NONE
method client isResizable NONE NONE NONE
method client isMovable NONE NONE NONE
method client isMovableAcrossScreens NONE NONE NONE
method client isCloseable NONE NONE NONE
PROPERTIES_DOC_LIST_END
PROPERTIES_DOC_DESC_START
# NOTES
# (m) workspace.getAllClients : Returns the client objects according to stacking order specified by an optional parameter which specifies the desktop nubmer to fetch the clients from. If no such parameter is provided, all clients are returned.
# (e) workspace.currentDesktopChanged : Occurs when the active desktop is changed. Parameters: prev_desktop
# (e) workspace.desktopPresenceChanged : Occurs when a client is switched from one desktop to another. Parameters: affected_client, prev_desktop
# (m) client.caption : Returns the caption of the client (or title in other terminologies)
# (e) client.clientMoved : Called when the client's geometry changed. Semantic error I know. Will be changed. TODO.
# (p) workspace.currentDesktop : Returns the current desktop of the workspace. Getter ONLY.
# (e) workspace.clientAdded : Called when a new client is added to the workspace. However, if there are clients already present when kwin is loaded, the C++ method. Workspace::clientAdded is called, but the script registered functions are not called. They are called ONLY for clients which are added after KWin has loaded. Maybe this will be fixed later, maybe not.
# (e) workspace.clientManaging: Called when a client is managed. Calls with one parameter, the client which is managed. NOTE: During this event, many of the client properties will not be available.
# (e) workspace.clientMinimize: Called when a client is minimized. Passes 1 parameter, the client which was minimized.
# (e) workspace.clientMaximizeSet: Called when the value of either of the two scalar dimensions of the client are set to the corresponding value of the workspace's dimensions or set to any other values FROM the corresponding values of the workspaces' dimensions. Passes 2 parameters, 1st being the client which is maximized and second specifying the vertically and horizontally hints.
# (m) client.close: Closes the given client. BTW: Just added client.close() within a function registered with workspace.clientAdded() to make a really annoying script ;)
# (e) workspace.killWindowCalled: Called whenever a kill window is requested [by default using the Ctrl+Esc sequence. Passes 1 param, the Client object of the Kill Window.
# (e) client.minimize: Called when the client is minimized. Called with no parameters.
# (e) client.maximizeSet: Similar to workspace.clientMaximizeSet other than for it's 1st parameter and called only when the event occurs on the specific client.
# (e) workspace.clientActivated: Called when any client gets focus. Called with one parameter: the client which was activated.
# (e) client.activated: Called when the object client gets activated.
#
# -- GEOMETRY PROPERTIES FOR TOPLEVEL --
# client inherits from toplevel i.e. toplevel properties are merged into the client scriptvalue before passing it to the
# scripting environment. Hence, all properties, methods and events of toplevel are available with the client object also
#
# (m) toplevel.x: Gives the x co-ordinate of the toplevel object.
# (m) toplevel.y: Gives the y co-ordinate of the toplevel object.
# (m) toplevel.width: Gives the width of the toplevel object.
# (m) toplevel.height: Givesn the height of the toplevel object.
# (m) toplevel.size: Returns the size in a QtScript object with properties of it's components. In JSON representation, the structure would be {w: <value>, h: <value>}.
# (m) toplevel.pos: Returns the posisition in a QtScript object with properties of it's components. In JSON representation, the structure would be {x: <value>, y: <value>}.
# (m) toplevel.geometry: Returns the complete geometry on a QtScript object with properties of it's components. In JSON representation, the structure would be [object] {x: <value>, y: <value>, w: <value>, h: <value>}
# (m) toplevel.move: Moves the client to the specified position.
# (m) toplevel.resize: Resized the client to the specified size.
# (m) toplevel.setGeometry: Set the geometry of the client to the specified size.
#
# -- For the three functions above --
#
# There are two methods to access each of these methods. One call can be made through using objects:
#
# client.move({x: <value>, y: <value>})
# client.resize({w: <value>, h: <value>})
# client.setGeometry({x: <value>, y: <value>, w: <value>, h: <value>})
#
# Or alternatively, using multiple parameters:
#
# client.move(x_value, y_value)
# client.resize(w_value, h_value)
# client.setGeometry(x_value, y_value, w_value, h_value)
#
# NOTE: For passing objects to these methods, the property names MUST match i.e. the move property expects properties
# 'x' and 'y' of the passed object.
#
# (m) client.isTransient : Returns (true) is 'client' is transient, (false) otherwise
# (m) client.transientFor : If the given client is transient, returns it's parent client, otherwise returns an undefin-
# ed scriptvalue.
# (m) client.activate : Attempt to focus the client, also send a parameter whether to force or not. However, focus stealing prevention still is activated and this may or may not actually focus the client.
# (m) client.setCaption : Set caption for the specified client.
# (m) workspace.dimensions : Returns the dimensions of the workspace. Accepts 1 string as a parameter which predates the the exact dimension to be returned. Default is "MaximizeMode"
# (m) workspace.desktopGridSize : Returns the size of the desktop in grid units.
# (m) client.isFullScreen : Returns true if the client is already in full screen mode.
# (m) client.isFullScreenable : Returns true if the client can be set in full screen mode.
# (m) client.setFullScreen : Set or clear full screen mode of the clientActivated
# (e) client.fullScreenSet : Occurs whenever the specified client is set to fullscreen.
# (e) workspace.clientFullScreenSet : Occurs whenever any client is set to fullscreen. Passes three params: client, set, user
# (m) toplevel.opacity : Returns a qsreal denoting the opacity of the cient.
# (m) toplevel.hasAlpha : Returns a boolean signifying whether the client has alpha compositing (porter-duff) enabled or not.
# (m) toplevel.setOpacity : Set the opacity of the client to a specified value. Accepts 1 qsreal parameter, the opacity value.
# (m) clientgroup.ClientGroup (ctor) : Constructor for a new ClientGroup object. Must pass a client object, otherwise returns an invalid scriptvalue.
# (m) clientgroup.add : Add a client to a client group. Expects 1 parameter.
# (m) workspace.activeClient : Returns the active client on the workspace i.e. the client which currently has focus.
# (m) workspace.clientGroups : Returns an array of clientGroups currently present in the workspace.
# (m) clientgroup.remove : Removes the client specified by the parameter which is either a client object or an index of the client in the clientlist.
# (m) clientgroup.clients : Returns an array of clients which are members of the clientgroup.
# (m) client.clientGroup : Returns the clientgroup a given client belongs to, or an undefined scriptvalue otherwise.
# (m) clientgroup.contains : Accepts a client parameter, and returns true the client is contained within the clientgroup
# (m) clientgroup.indexOf : Returns the index of the parameter 'client' within the clientgroup
# (m) clientgroup.move : Move a client within the group. Accepts move(client, client), move(index, index), move(index, client), move(client, index). All calls except move(client, client) are eventually mapped to move(index, index) using indexOf(client)
# (m) clientgroup.removeAll : Removes all clients from a group and assigns them individual groups.
# (m) clientgroup.closeAll : Closes all the clients in a group.
# (m) clientgroup.minSize : Returns the minimum size cumulative of all the clients in the clientgroup.
# (m) clientgroup.maxSize : Returns the maximum size cumulative of all the clients in the clientgroup.
# (p) config.loaded : Returns true if a file corresponding to the script has been found and loaded.
# (m) config.get : Gets the value for the given configuration parameters. Various methods to use this are: get() returns all available values in a value-key pair. get(keys, simple) returns an array of value indexed by keys if simple is 0 or indexed by integers if simple is 1. get(keys) is equivalent of get(keys, 0). get(key1, key2 ... ) is equivalent of get(array(key1, key2 ... ), 0).
# (m) config.exists : Returns true if the provided key exists within the configuration or false otherwise.
# (m) client.desktop : Returns the desktop the client is on. Returns -1 if the client is on all desktops.
# (m) client.isShade : Returns true if the client is shaded, false otherwise.
# (m) client.isShadeable : Returns true if the client can be shaded, false otherwise.
# (m) client.isMinimized : Returns true if the client is minimized, false otherwise.
# (m) client.isMinimizable : Returns true if the client can be minimized, false otherwise.
# (m) client.isMaximizable : Returns true if the client can be maximized, false otherwise.
# (m) client.isResizable : Returns true if the client can be resized, false otherwise.
# (m) client.isMovable : Returns true if the client can be moved, false otherwise.
# (m) client.isMovableAcrossScreens : Returns true if the client can be moved across screens, false otherwise.
# (m) client.isCloseable : Returns true if the client can be closed, false otherwise.
PROPERTIES_DOC_DESC_END

393
scripting/chelate.cpp Normal file
View File

@ -0,0 +1,393 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "chelate.h"
#include "meta.h"
QList<KWin::Chelate::ChelateProxy*> KWin::Chelate::ChelateProxy::chMap;
/**
* ChelateProxy | functions
*/
KWin::Chelate::ChelateProxy::ChelateProxy()
{
engine = 0;
}
void KWin::Chelate::ChelateProxy::setEngine(QScriptEngine* _engine)
{
engine = _engine;
}
void KWin::Chelate::ChelateProxy::setConnectors(QScriptValueList _connectors)
{
connectors = _connectors;
}
void KWin::Chelate::ChelateProxy::setAction(QScriptValue _action)
{
action = _action;
}
void KWin::Chelate::ChelateProxy::setEventStrings(QStringList _on)
{
on = _on;
}
void KWin::Chelate::ChelateProxy::setFilter(QScriptValue _filter)
{
filter = _filter;
}
void KWin::Chelate::ChelateProxy::setId(int _id)
{
id = _id;
}
QScriptValue KWin::Chelate::ChelateProxy::getAction()
{
return action;
}
QScriptValue KWin::Chelate::ChelateProxy::getFilter()
{
return filter;
}
void KWin::Chelate::ChelateProxy::process(int index)
{
if(engine == 0)
{
return;
}
QScriptValue connector = connectors.at(index).property("connect");
QScriptValue _scanner = engine->newFunction(KWin::Chelate::scanner, 0);
_scanner.setData(engine->fromScriptValue<int>(id));
QScriptValueList args;
args<<_scanner;
connector.call(connectors.at(index), args);
}
void KWin::Chelate::ChelateProxy::processAll()
{
for(int i = 0; i<connectors.size(); i++)
{
process(i);
}
}
/** */
// END of ChelateProxy | functions
/** */
/**
* KWin::Chelate | functions
*/
QScriptValue KWin::Chelate::scanner(QScriptContext* ctx, QScriptEngine* eng)
{
QScriptValue index = (ctx->callee()).data();
KWin::Chelate::ChelateProxy* proxy = KWin::Chelate::ChelateProxy::chMap.at(index.toNumber());
QScriptValue filter = proxy->getFilter();
bool ret = (filter.call(QScriptValue(), ctx->argumentsObject())).toBool();
if(ret == true)
{
QScriptValue action = proxy->getAction();
action.call(QScriptValue(), ctx->argumentsObject());
}
return eng->undefinedValue();
}
QScriptValue KWin::Chelate::rule(QScriptContext* ctx, QScriptEngine* eng)
{
ChelateProxy* proxy = new ChelateProxy();
QScriptValue chRule = eng->newObject();
QScriptValue ruleObj;
if(ctx->argumentCount() > 0)
{
ruleObj = ctx->argument(0);
}
else
{
return eng->undefinedValue();
}
/**
* First, process the events that are to be hooked on to
*/
if(ruleObj.property("on").isValid() && !ruleObj.property("on").isUndefined())
{
QStringList eventStrings;
QScriptValueList connectors;
QScriptValueIterator it(ruleObj.property("on"));
while (it.hasNext())
{
it.next();
QScriptValue connector = (eng->globalObject()).property("workspace").property(it.value().toString());
if(connector.isValid() && !connector.isUndefined())
{
eventStrings<<it.value().toString();
connectors<<connector;
}
}
proxy->setConnectors(connectors);
proxy->setEventStrings(eventStrings);
}
/**
* Then we have our filters.. the most daring part of KWin Scripting yet :)
* Actually this is pretty simple here, but just wait to see
* Chelate LazyLogic (tm)
*/
if(ruleObj.property("filter").isValid() && !ruleObj.property("filter").isUndefined())
{
QScriptValue filter = ruleObj.property("filter");
if(filter.isFunction())
{
proxy->setFilter(filter);
}
}
if(ruleObj.property("action").isValid() && !ruleObj.property("action").isUndefined())
{
QScriptValue action = ruleObj.property("action");
if(action.isFunction())
{
proxy->setAction(action);
}
}
proxy->setEngine(eng);
proxy->setId(KWin::Chelate::ChelateProxy::chMap.size());
KWin::Chelate::ChelateProxy::chMap.append(proxy);
proxy->processAll();
return chRule;
}
QScriptValue KWin::Chelate::publishChelate(QScriptEngine* eng)
{
QScriptValue temp = eng->newObject();
temp.setProperty("rule", eng->newFunction(KWin::Chelate::rule, 1), QScriptValue::Undeletable);
temp.setProperty("and", KWin::MetaScripting::getLazyLogicFunction(eng, "ll_and"), QScriptValue::Undeletable);
temp.setProperty("or", KWin::MetaScripting::getLazyLogicFunction(eng, "ll_or"), QScriptValue::Undeletable);
temp.setProperty("not", KWin::MetaScripting::getLazyLogicFunction(eng, "ll_not"), QScriptValue::Undeletable);
temp.setProperty("equiv", eng->newFunction(KWin::Chelate::chelationEquivGen, 0), QScriptValue::Undeletable);
temp.setProperty("regex", eng->newFunction(KWin::Chelate::chelationRegexGen, 0), QScriptValue::Undeletable);
return temp;
}
/**
* Chelation functions. These functions are used to filter
* the incoming clients.
*/
QScriptValue KWin::Chelate::chelationRegex(QScriptContext* ctx, QScriptEngine* eng)
{
QScriptValue key = ((ctx->callee()).data()).property("key");
QScriptValue regex = ((ctx->callee()).data()).property("regex");
QScriptValue post = ((ctx->callee()).data()).property("post");
QRegExp re(regex.toString());
if(!key.isUndefined() && !regex.isUndefined())
{
QScriptValue scCentral = ctx->argument(0);
QScriptValue callBase = scCentral.property(key.toString());
QString final = (callBase.isFunction())?((callBase.call(scCentral)).toString()):(callBase.toString());
int pos = re.indexIn(final);
if(post.isUndefined())
{
if(pos > -1)
{
return eng->toScriptValue<bool>(1);
}
else
{
return eng->toScriptValue<bool>(0);
}
}
else
{
QScriptValueList args;
QStringList list = re.capturedTexts();
args<<eng->toScriptValue<QStringList>(re.capturedTexts());
return eng->toScriptValue<bool>((post.call(QScriptValue(), args)).toBool());
}
}
else
{
return eng->toScriptValue<bool>(0);
}
}
QScriptValue KWin::Chelate::chelationRegexGen(QScriptContext* ctx, QScriptEngine* eng)
{
QScriptValue func = eng->newFunction(chelationRegex, 0);
QScriptValue data = eng->newObject();
data.setProperty("key", ctx->argument(0));
data.setProperty("regex", ctx->argument(1));
data.setProperty("post", ctx->argument(2));
func.setData(data);
return func;
}
QScriptValue KWin::Chelate::chelationEquiv(QScriptContext* ctx, QScriptEngine* eng)
{
QScriptValue key = ((ctx->callee()).data()).property("key");
QScriptValue value = ((ctx->callee()).data()).property("value");
if(!key.isUndefined() && !value.isUndefined())
{
QScriptValue scCentral = ctx->argument(0);
QScriptValue callBase = scCentral.property(key.toString());
QString final = (callBase.isFunction())?((callBase.call(scCentral)).toString()):(callBase.toString());
return eng->toScriptValue<bool>(final.compare(value.toString(), Qt::CaseInsensitive) == 0);
}
else
{
return eng->toScriptValue<bool>(0);
}
}
QScriptValue KWin::Chelate::chelationEquivGen(QScriptContext* ctx, QScriptEngine* eng)
{
QScriptValue func = eng->newFunction(chelationEquiv, 0);
QScriptValue data = eng->newObject();
data.setProperty("key", ctx->argument(0));
data.setProperty("value", ctx->argument(1));
func.setData(data);
return func;
}
QScriptValue KWin::Chelate::chelationCheck(QScriptContext* ctx, QScriptEngine* eng)
{
QScriptValue key = ((ctx->callee()).data()).property("key");
if(!key.isUndefined())
{
QScriptValue scCentral = ctx->argument(0);
QScriptValue callBase = scCentral.property(key.toString());
return (callBase.isFunction())?((callBase.call(scCentral)).toBool()):(callBase.toBool());
}
}
QScriptValue KWin::Chelate::chelationCheckGen(QScriptContext* ctx, QScriptEngine* eng)
{
QScriptValue func = eng->newFunction(chelationCheck, 0);
QScriptValue data = eng->newObject();
data.setProperty("key", ctx->argument(0));
func.setData(data);
return func;
}
/** */
/** LazyLogic (tm) */
/** */
QScriptValue KWin::Chelate::lazyLogicGenerate(QScriptContext* ctx, QScriptEngine* eng)
{
// Assume everything as necessary. If enough or wrong parameters
// are provided, undefined values are used and then the function call
// fails silently (it is non-fatal)
QScriptValue type = (((ctx->callee()).data()).property("lazylogic_type"));
QString typeString = type.toString();
if(!((typeString == "ll_and") || (typeString == "ll_or") || (typeString == "ll_not") || (typeString == "ll_xor")))
{
return eng->undefinedValue();
}
QScriptValue func = eng->newFunction(KWin::Chelate::lazyLogic, 0);
QScriptValue data = eng->newObject();
data.setProperty("lazylogic_type", type);
data.setProperty("lazylogic_operands", ctx->argumentsObject());
func.setData(data);
return func;
}
QScriptValue KWin::Chelate::lazyLogic(QScriptContext* ctx, QScriptEngine* eng)
{
bool init;
QString type = (((ctx->callee()).data()).property("lazylogic_type")).toString();
QScriptValue operands = ((ctx->callee()).data()).property("lazylogic_operands");
if(type == "ll_and")
{
init = 1;
}
else if(type == "ll_or")
{
init = 0;
}
else if(type == "ll_not")
{
QScriptValue current = operands.property("0");
return !(current.isFunction())?((current.call(QScriptValue(), ctx->argumentsObject())).toBool()):(current.toBool());
}
else if(type == "ll_xor")
{
QScriptValue _current = operands.property("0");
QScriptValue current = operands.property("1");
return (( current.isFunction())?(( current.call(QScriptValue(), ctx->argumentsObject())).toBool()): current.toBool() ^
(_current.isFunction())?((_current.call(QScriptValue(), ctx->argumentsObject())).toBool()):_current.toBool()
);
}
else
{
return eng->toScriptValue<bool>(0);
}
for(int i=0; i<operands.property("length").toNumber(); i++)
{
QScriptValue current = operands.property(QString::number(i));
if(current.isFunction())
{
if(type == "ll_and")
{
init = init && (current.isFunction())?((current.call(QScriptValue(), ctx->argumentsObject())).toBool()):(current.toBool());
}
else if(type == "ll_or")
{
init = init || (current.isFunction())?((current.call(QScriptValue(), ctx->argumentsObject())).toBool()):(current.toBool());
}
}
}
return eng->toScriptValue<bool>(init);
}
/** */
// END of KWin::Chelate | functions
/** */

121
scripting/chelate.h Normal file
View File

@ -0,0 +1,121 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
/********************************************************************
* ***
** *** *
** ** **
** ** **
** ** ********
**** ** *** *** ** **** ******** ***
* *** * ** * *** * *** ** * *** * ** * ***
* **** *** *** * *** ** * **** ** * ***
** ** ** ** *** ** ** ** ** ** ***
** ** ** ******** ** ** ** ** ********
** ** ** ******* ** ** ** ** *******
** ** ** ** ** ** ** ** **
*** * ** ** **** * ** ** ** ** **** *
******* ** ** ******* *** * ***** ** ** *******
***** ** ** ***** *** *** ** *****
*
* The most exciting thing that ever happened to
* KWin::Scripting. With LazyLogic (tm)
*
*********************************************************************/
#ifndef __KWIN__SCRIPTING_CHELATE_H
#define __KWIN__SCRIPTING_CHELATE_H
#include <QScriptClass>
#include <QList>
#include <QScriptEngine>
#include "workspace.h"
#include "client.h"
/**
* Chelate forms a very different kind of singleton structure.
* It's functions are designed to mostly provide ample space
* and environment for lazy evaluations. Chelate is mostly cute.
*/
namespace KWin
{
namespace Chelate
{
/**
* A class used to store data about each chelate rule.
*/
class ChelateProxy
{
private:
QStringList on;
QScriptValueList connectors;
QScriptValue filter;
QScriptValue action;
int id;
QScriptEngine* engine;
public:
void setAction(QScriptValue);
void setFilter(QScriptValue);
void setEventStrings(QStringList);
void setConnectors(QScriptValueList);
void setEngine(QScriptEngine*);
void setId(int);
QScriptValue getAction();
QScriptValue getFilter();
static QList<ChelateProxy*> chMap;
void processAll();
void process(int);
ChelateProxy();
};
QScriptValue scanner(QScriptContext*, QScriptEngine*);
QScriptValue rule(QScriptContext*, QScriptEngine*);
QScriptValue publishChelate(QScriptEngine* engine);
/** Chelation */
QScriptValue chelationEquivGen(QScriptContext*, QScriptEngine*);
QScriptValue chelationEquiv(QScriptContext*, QScriptEngine*);
QScriptValue chelationCheckGen(QScriptContext*, QScriptEngine*);
QScriptValue chelationCheck(QScriptContext*, QScriptEngine*);
QScriptValue chelationRegexGen(QScriptContext*, QScriptEngine*);
QScriptValue chelationRegex(QScriptContext*, QScriptEngine*);
/** */
/** LazyLogic (tm) */
/** */
QScriptValue lazyLogicGenerate(QScriptContext*, QScriptEngine*);
QScriptValue lazyLogic(QScriptContext*, QScriptEngine*);
};
};
#endif

607
scripting/client.cpp Normal file
View File

@ -0,0 +1,607 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "client.h"
SWrapper::Client::Client(KWin::Client* client) :
Toplevel(client)
{
if(client != 0)
{
QObject::connect(client, SIGNAL(s_clientMoved()), this, SLOT(sl_clientMoved()));
QObject::connect(client, SIGNAL(maximizeSet(QPair<bool, bool>)), this, SLOT(sl_maximizeSet(QPair<bool, bool>)));
QObject::connect(client, SIGNAL(s_minimized()), this, SIGNAL(minimized()));
QObject::connect(client, SIGNAL(s_activated()), this, SIGNAL(gotFocus()));
QObject::connect(client, SIGNAL(s_fullScreenSet(bool, bool)), this, SIGNAL(fullScreenSet(bool, bool)));
QObject::connect(client, SIGNAL(s_unminimized()), this, SIGNAL(unminimized()));
QObject::connect(this, SIGNAL(unminimized()), this, SIGNAL(restored()));
}
centralObject = client;
}
KWin::Client* SWrapper::Client::getCentralObject()
{
return centralObject;
}
/*
SWrapper::ClientResolution SWrapper::Client::clientResolve(const QScriptEngine*, const KWin::Client* client) {
if(client == 0) {
return ClientResolution(0, QScriptValue());
} else {
return
}
}
*/
void SWrapper::Client::setEngine(QScriptEngine* eng)
{
engine = eng;
}
void SWrapper::Client::sl_clientMoved()
{
emit clientMoved();
}
void SWrapper::Client::sl_maximizeSet(QPair<bool, bool> param)
{
QScriptValue temp = engine->newObject();
temp.setProperty("v", engine->toScriptValue(param.first));
temp.setProperty("h", engine->toScriptValue(param.second));
emit maximizeSet(temp);
}
/*
bool SWrapper::Client::clientRelease(const KWin::Client* client) {
if(client == 0) {
return false;
} else {
if(client->swrapper != 0) {
delete client->swrapper;
return true;
}
}
return false;
}
*/
//newWrapper does not search clientMap for existing entries
//a search must be performed prior to this call.
//However, since now clientMap is actually a QHash, it wouldn't
//hurt to perform a check here as well.
SWrapper::ClientResolution SWrapper::Client::newWrapper(KWin::Client* client, QScriptEngine* eng)
{
SWrapper::Client* wrapper = new SWrapper::Client(client);
wrapper->setEngine(eng);
QScriptValue value;
// Use this value to avoid repeated function generations
// for function aliases.
QScriptValue func;
/*
* Step1: Prepping
* Connect all signals and slots from client to
* the wrapper object.
*/
//End of prepping
/*
* Step2: Conversion
* Wrap the object, set the data parameter
* and obtain a QScriptValue
*/
value = eng->newQObject(wrapper,
QScriptEngine::AutoOwnership,
QScriptEngine::ExcludeSuperClassContents | QScriptEngine::ExcludeDeleteLater
);
wrapper->tl_centralObject = client;
tl_append(value, eng);
//End of Conversion
/*
* Step3: Spice
* Add the static functions and other things
* that rely on the value of data() and not the
* wrapper address.
*/
value.setProperty("caption", eng->newFunction(caption, 0), QScriptValue::Undeletable);
value.setProperty("close", eng->newFunction(close, 0), QScriptValue::Undeletable);
value.setProperty("resize", eng->newFunction(resize, 1), QScriptValue::Undeletable);
value.setProperty("move", eng->newFunction(move, 1), QScriptValue::Undeletable);
value.setProperty("setGeometry", eng->newFunction(setGeometry, 1), QScriptValue::Undeletable);
value.setProperty("getWindowInfo", eng->newFunction(getWindowInfo, 0), QScriptValue::Undeletable);
value.setProperty("isTransient", eng->newFunction(isTransient, 0), QScriptValue::Undeletable);
value.setProperty("transientFor", eng->newFunction(transientFor, 0), QScriptValue::Undeletable);
value.setProperty("activate", eng->newFunction(activate, 1), QScriptValue::Undeletable);
value.setProperty("setCaption", eng->newFunction(setCaption, 1), QScriptValue::Undeletable);
value.setProperty("setFullScreen", eng->newFunction(setFullScreen, 2), QScriptValue::Undeletable);
value.setProperty("isFullScreen", eng->newFunction(isFullScreen, 0), QScriptValue::Undeletable);
value.setProperty("isFullScreenable", eng->newFunction(isFullScreenable, 0), QScriptValue::Undeletable);
value.setProperty("minimize", eng->newFunction(minimize, 0), QScriptValue::Undeletable);
value.setProperty("clientGroup", eng->newFunction(clientGroup, 0), QScriptValue::Undeletable);
value.setProperty("maximize", eng->newFunction(maximize, 0), QScriptValue::Undeletable);
value.setProperty("setMaximize", eng->newFunction(setMaximize, 2), QScriptValue::Undeletable);
value.setProperty("desktop", eng->newFunction(desktop, 0), QScriptValue::Undeletable);
BOOLATTACHCLIENT(isShade)
BOOLATTACHCLIENT(isShadeable)
BOOLATTACHCLIENT(isMinimized)
BOOLATTACHCLIENT(isMinimizable)
BOOLATTACHCLIENT(isMaximizable)
BOOLATTACHCLIENT(isResizable)
BOOLATTACHCLIENT(isMovable)
BOOLATTACHCLIENT(isMovableAcrossScreens)
BOOLATTACHCLIENT(isCloseable)
func = eng->newFunction(unminimize, 0);
value.setProperty("unminimize", func, QScriptValue::Undeletable);
value.setProperty("restore", func, QScriptValue::Undeletable);
ClientResolution final(wrapper, value);
//Finally, append the entire thing to the clientMap
//clientMap.insert(const_cast<KWin::Client*>(client), ClientResolution(wrapper, value));
//And.. we're done
(client->scriptCache)->insert(eng, final);
return final;
}
QScriptValue SWrapper::Client::generate(KWin::Client* client, QScriptEngine* eng)
{
if(client == 0)
{
return QScriptValue();
}
else
{
ClientResolution res = (client->scriptCache)->value(eng, ClientResolution(0, QScriptValue()));
if(res.first != 0)
{
//The required object has been already created
//Return that instead of creating a new one
return res.second;
}
else
{
res = newWrapper(client, eng);
return res.second;
}
}
}
QScriptValue SWrapper::Client::setMaximize(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
if(central == 0)
{
return eng->toScriptValue<bool>(0);
}
else
{
central->setMaximize((ctx->argument(0)).toBool(), (ctx->argument(1)).toBool());
return eng->toScriptValue<bool>(1);
}
}
BOOLEXPORTCLIENT(isShade)
BOOLEXPORTCLIENT(isShadeable)
BOOLEXPORTCLIENT(isMinimized)
BOOLEXPORTCLIENT(isMinimizable)
BOOLEXPORTCLIENT(isMaximizable)
BOOLEXPORTCLIENT(isResizable)
BOOLEXPORTCLIENT(isMovable)
BOOLEXPORTCLIENT(isMovableAcrossScreens)
BOOLEXPORTCLIENT(isCloseable)
QScriptValue SWrapper::Client::isNormal(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
if(central == 0)
{
return eng->undefinedValue();
}
else
{
return eng->toScriptValue<bool>(!central->isSpecialWindow());
}
}
QScriptValue SWrapper::Client::maximize(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
if(central == 0)
{
return eng->toScriptValue<bool>(0);
}
else
{
central->setMaximize(1, 1);
return eng->toScriptValue<bool>(1);
}
}
QScriptValue SWrapper::Client::desktop(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
if(central == 0)
{
return eng->undefinedValue();
}
else
{
return eng->toScriptValue(central->desktop());
}
}
QScriptValue SWrapper::Client::clientGroup(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
if(central == 0)
{
return QScriptValue();
}
else
{
return eng->toScriptValue<KWin::ClientGroup*>(central->clientGroup());
}
}
QScriptValue SWrapper::Client::caption(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
if(central == 0)
{
return QScriptValue();
}
else
{
return eng->toScriptValue(central->caption());
}
}
QScriptValue SWrapper::Client::setCaption(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
if(ctx->argument(0).isUndefined())
{
return eng->toScriptValue<bool>(0);
}
else
{
QString cap = (ctx->argument(0)).toString();
central->setCaption(cap);
return eng->toScriptValue<bool>(1);
}
}
QScriptValue SWrapper::Client::resize(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
QScriptValue arg = ctx->argument(0);
QSize size;
bool emitJs;
QScriptValue emitJsQs;
if(central == 0 || arg.isUndefined())
{
return eng->toScriptValue<bool>(0);
}
else
{
if(arg.isNumber())
{
size = QSize(arg.toInt32(), (ctx->argument(1)).toInt32());
emitJsQs = ctx->argument(2);
}
else if(arg.isObject())
{
size = eng->fromScriptValue<QSize>(arg);
emitJsQs = ctx->argument(1);
}
if(emitJsQs.isUndefined() || !emitJsQs.isValid())
{
emitJs = true;
}
else
{
emitJs = emitJsQs.toBool();
}
if(size.isValid())
{
central->plainResize(size, KWin::NormalGeometrySet, emitJs);
return eng->toScriptValue<bool>(0);
}
else
{
return eng->toScriptValue<bool>(1);
}
}
}
QScriptValue SWrapper::Client::move(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
QScriptValue arg = ctx->argument(0);
if(central == 0 || arg.isUndefined())
{
return eng->toScriptValue<bool>(0);
}
else
{
QPoint point;
bool emitJs;
QScriptValue emitJsQs;
if(arg.isNumber())
{
point = QPoint(arg.toInt32(), (ctx->argument(1)).toInt32());
emitJsQs = ctx->argument(2);
}
else if(arg.isObject())
{
point = eng->fromScriptValue<QPoint>(arg);
emitJsQs = ctx->argument(1);
}
if(emitJsQs.isUndefined() || !emitJsQs.isValid())
{
emitJs = true;
}
else
{
emitJs = emitJsQs.toBool();
}
central->setGeometry(QRect(point, central->size()), KWin::NormalGeometrySet, emitJs);
return eng->toScriptValue<bool>(1);
}
}
QScriptValue SWrapper::Client::setGeometry(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
QScriptValue arg = ctx->argument(0);
QRect rect;
bool emitJs;
QScriptValue emitJsQs;
if(central == 0 || arg.isUndefined())
{
return eng->toScriptValue<bool>(0);
}
else
{
if(arg.isNumber())
{
rect = QRect(arg.toInt32(), (ctx->argument(1)).toInt32(),
(ctx->argument(2)).toInt32(), (ctx->argument(3)).toInt32());
emitJsQs = ctx->argument(4);
}
else if(arg.isObject())
{
rect = eng->fromScriptValue<QRect>(arg);
emitJsQs = ctx->argument(1);
}
if(emitJsQs.isUndefined() || !emitJsQs.isValid())
{
emitJs = true;
}
else
{
emitJs = emitJsQs.toBool();
}
central->setGeometry(rect, KWin::NormalGeometrySet, emitJs);
return eng->toScriptValue<bool>(1);
}
}
QScriptValue SWrapper::Client::getWindowInfo(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
if(central == 0)
{
return QScriptValue();
}
else
{
// For now atleast, just get all propeties. Tweaking will be taken care
// of later. TODO
KWindowInfo info = KWindowSystem::windowInfo(central->window(), -1U, -1U);
return SWrapper::WindowInfo::generate(info, eng, central);
}
}
/*
QString SWrapper::Client::caption() {
return centralObject->caption();
}*/
QScriptValue SWrapper::Client::unminimize(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
if(central == 0)
{
return eng->toScriptValue<bool>(0);
}
else
{
central->unminimize(false);
return eng->toScriptValue<bool>(1);
}
}
QScriptValue SWrapper::Client::minimize(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
if(central == 0)
{
return eng->toScriptValue<bool>(0);
}
else
{
central->minimize(false);
return eng->toScriptValue<bool>(1);
}
}
QScriptValue SWrapper::Client::close(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
if(central == 0)
{
return QScriptValue();
}
else
{
central->closeWindow();
return eng->toScriptValue(true);
}
}
QScriptValue SWrapper::Client::isTransient(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
if(central == 0)
{
return QScriptValue();
}
else
{
bool x = central->isTransient();
return eng->toScriptValue(x);
}
}
QScriptValue SWrapper::Client::transientFor(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
if(central == 0)
{
return QScriptValue();
}
else
{
return eng->toScriptValue(central->transientFor());
}
}
QScriptValue SWrapper::Client::setFullScreen(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
QScriptValue set = ctx->argument(0);
QScriptValue user = ctx->argument(0);
if(set.isUndefined() || user.isUndefined())
{
return QScriptValue();
}
if(central == 0)
{
return eng->toScriptValue<bool>(0);
}
else
{
central->setFullScreen(set.toBool(), user.toBool());
return eng->toScriptValue<bool>(1);
}
}
QScriptValue SWrapper::Client::isFullScreen(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
if(central == 0)
{
return QScriptValue();
}
else
{
return eng->toScriptValue<bool>(central->isFullScreen());
}
}
QScriptValue SWrapper::Client::isFullScreenable(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
if(central == 0)
{
return QScriptValue();
}
else
{
return eng->toScriptValue<bool>(central->isFullScreenable());
}
}
QScriptValue SWrapper::Client::activate(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject());
QScriptValue force = ctx->argument(0);
bool _force = 0;
if(central == 0)
{
return eng->toScriptValue<bool>(0);
}
else
{
if(!force.isBool())
{
_force = force.toBool();
}
(KWin::Workspace::self())->activateClient(central, _force);
return eng->toScriptValue<bool>(1);
}
}

183
scripting/client.h Normal file
View File

@ -0,0 +1,183 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef __KWIN__SCRIPTING_CLIENT_H
#define __KWIN__SCRIPTING_CLIENT_H
#include <QDebug>
#include "./../workspace.h"
#include "./../client.h"
#include "toplevel.h"
#include "windowinfo.h"
#include "meta.h"
#include <QScriptEngine>
#include <QPair>
/**
* BOOLEXPORTCLIENT and BOOLATTACHCLIENT are together used to export and connect
* functions like client.isMaximizable, client.isShaded etc.
*/
#define BOOLEXPORTCLIENT(name) \
QScriptValue SWrapper::Client::name(QScriptContext* ctx, QScriptEngine* eng) { \
KWin::Client* central = eng->fromScriptValue<KWin::Client*>(ctx->thisObject()); \
\
if(central == 0) { \
return eng->undefinedValue(); \
} else { \
return eng->toScriptValue<bool>(central->name()); \
} \
}
#define BOOLATTACHCLIENT(name) \
value.setProperty(#name, eng->newFunction(name, 0), QScriptValue::Undeletable);
namespace SWrapper
{
class Client;
/**
* ClientResolution is a nice placeholder for a SWrapper::Client
* and the corresponding QScriptValue that is generated.
*/
typedef QPair<SWrapper::Client*, QScriptValue> ClientResolution;
class Client : public Toplevel
{
Q_OBJECT
//Q_PROPERTY(QString caption READ caption)
private:
//No longer using a vector for client-qsvalue mapping
//static QVector<ClientMapper*> clientMap;
//We're using QHash instead!!
//We're not even using QHash anymore :)
/** Generates a new wrapper and a corresponding QScriptValue
* and returns it as a ClientResolution
*/
static ClientResolution newWrapper(KWin::Client*, QScriptEngine*);
/**
* The KWin::Client* object that this wrapper handles
* or 'wraps'.
*/
KWin::Client* centralObject;
/**
* The QScriptEngine this wrapper is associated with
*/
QScriptEngine* engine;
private slots:
/**
* Emitted when the client is moved or resized
*/
void sl_clientMoved();
/**
* Emitted when the client is maximized
*/
void sl_maximizeSet(QPair<bool, bool>);
signals:
/**
* Various events of the client.
*/
void clientMoved();
/**
* The parameter is a two-element object in the format
* {horizontally, vertically}
*/
void maximizeSet(QScriptValue);
void minimized();
void gotFocus();
void fullScreenSet(bool, bool);
void unminimized();
void restored();
public:
Client(KWin::Client*);
//static bool clientRelease(const KWin::Client*);
/**
* Generate a new QScriptValue. This function can be directly used
* by outside functions as it handles looking up the cache,
* generation and validation of the cache
*/
static QScriptValue generate(KWin::Client*, QScriptEngine*);
/**
* Sets the QScriptEngine for the current wrapper
*/
void setEngine(QScriptEngine*);
/**
* Returns the KWin::Client* object this wrapper 'wraps'
*/
KWin::Client* getCentralObject();
// Forwaded functions: These functions emit signals, just like the sl_
// signals, however, the client object is not available and hence
// must be resolved. These are not slots and hence must be called i.e.
// they cannot be connected to any signal.
static void fw_clientActivated(KWin::Client*);
/**
* A variety of functions, all are self-explanatory.
*/
static QScriptValue caption(QScriptContext*, QScriptEngine*);
static QScriptValue close(QScriptContext*, QScriptEngine*);
static QScriptValue resize(QScriptContext*, QScriptEngine*);
static QScriptValue move(QScriptContext*, QScriptEngine*);
static QScriptValue setGeometry(QScriptContext*, QScriptEngine*);
static QScriptValue getWindowInfo(QScriptContext*, QScriptEngine*);
static QScriptValue isTransient(QScriptContext*, QScriptEngine*);
static QScriptValue transientFor(QScriptContext*, QScriptEngine*);
static QScriptValue activate(QScriptContext*, QScriptEngine*);
static QScriptValue setCaption(QScriptContext*, QScriptEngine*);
static QScriptValue setFullScreen(QScriptContext*, QScriptEngine*);
static QScriptValue isFullScreen(QScriptContext*, QScriptEngine*);
static QScriptValue isFullScreenable(QScriptContext*, QScriptEngine*);
static QScriptValue unminimize(QScriptContext*, QScriptEngine*);
static QScriptValue minimize(QScriptContext*, QScriptEngine*);
static QScriptValue clientGroup(QScriptContext*, QScriptEngine*);
static QScriptValue setMaximize(QScriptContext*, QScriptEngine*);
static QScriptValue maximize(QScriptContext*, QScriptEngine*);
static QScriptValue desktop(QScriptContext*, QScriptEngine*);
static QScriptValue isShade(QScriptContext*, QScriptEngine*);
static QScriptValue isShadeable(QScriptContext*, QScriptEngine*);
static QScriptValue isMinimized(QScriptContext*, QScriptEngine*);
static QScriptValue isMinimizable(QScriptContext*, QScriptEngine*);
static QScriptValue isMaximizable(QScriptContext*, QScriptEngine*);
static QScriptValue isResizable(QScriptContext*, QScriptEngine*);
static QScriptValue isMovable(QScriptContext*, QScriptEngine*);
static QScriptValue isMovableAcrossScreens(QScriptContext*, QScriptEngine*);
static QScriptValue isCloseable(QScriptContext*, QScriptEngine*);
static QScriptValue isNormal(QScriptContext*, QScriptEngine*);
};
}
#endif

313
scripting/meta.cpp Normal file
View File

@ -0,0 +1,313 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "meta.h"
Q_DECLARE_METATYPE(SWrapper::Client*)
Q_DECLARE_METATYPE(SWrapper::ClientGroup*)
using namespace KWin::MetaScripting;
// Wrapper for KWin::Client* objects
QScriptValue Client::toScriptValue(QScriptEngine* eng, const KClientRef& client)
{
return SWrapper::Client::generate(client, eng);
}
void Client::fromScriptValue(const QScriptValue& obj, KWin::Client*& client)
{
SWrapper::Client* wrapper = qscriptvalue_cast<SWrapper::Client*>(obj);
if(wrapper == 0)
{
client = 0;
}
else
{
client = wrapper->getCentralObject();
}
}
// End of metas for KWin::Client* objects
// Meta for KWin::ClientGroup* objects
QScriptValue ClientGroup::toScriptValue(QScriptEngine* eng, const KClientGroupRef& cGrp)
{
return SWrapper::ClientGroup::generate(eng, new SWrapper::ClientGroup(cGrp));
}
void ClientGroup::fromScriptValue(const QScriptValue& obj, KWin::ClientGroup*& cGrp)
{
SWrapper::ClientGroup* wrapper = qscriptvalue_cast<SWrapper::ClientGroup*>(obj);
if(wrapper == 0)
{
cGrp = 0;
}
else
{
cGrp = wrapper->getCentralObject();
}
}
// End of metas for KWin::ClientGroup* objects
// Wrapper for KWin::Toplevel* objects [ONE DIRTY HACK]
QScriptValue Toplevel::toScriptValue(QScriptEngine* eng, const KToplevelRef& tlevel)
{
Q_UNUSED(eng)
Q_UNUSED(tlevel)
return QScriptValue();
}
void Toplevel::fromScriptValue(const QScriptValue& obj, KWin::Toplevel*& tlevel)
{
SWrapper::Client* wrapper = qscriptvalue_cast<SWrapper::Client*>(obj);
if(wrapper == 0)
{
tlevel = 0;
}
else
{
tlevel = static_cast<KWin::Client*>(wrapper->getCentralObject());
}
}
// End of wrapper for KWin::Toplevel* object
// Meta for QPoint object
QScriptValue Point::toScriptValue(QScriptEngine* eng, const QPoint& point)
{
QScriptValue temp = eng->newObject();
temp.setProperty("x", point.x());
temp.setProperty("y", point.y());
return temp;
}
void Point::fromScriptValue(const QScriptValue& obj, QPoint& point)
{
QScriptValue x = obj.property("x", QScriptValue::ResolveLocal);
QScriptValue y = obj.property("y", QScriptValue::ResolveLocal);
if(!x.isUndefined() && !y.isUndefined())
{
point.setX(x.toInt32());
point.setY(y.toInt32());
}
}
// End of meta for QPoint object
// Meta for QSize object
QScriptValue Size::toScriptValue(QScriptEngine* eng, const QSize& size)
{
QScriptValue temp = eng->newObject();
temp.setProperty("w", size.width());
temp.setProperty("h", size.height());
return temp;
}
void Size::fromScriptValue(const QScriptValue& obj, QSize& size)
{
QScriptValue w = obj.property("w", QScriptValue::ResolveLocal);
QScriptValue h = obj.property("h", QScriptValue::ResolveLocal);
if(!w.isUndefined() && !h.isUndefined())
{
size.setWidth(w.toInt32());
size.setHeight(h.toInt32());
}
}
// End of meta for QSize object
// Meta for QRect object. Just a temporary measure, hope to
// add a much better wrapping of the QRect object soon
QScriptValue Rect::toScriptValue(QScriptEngine* eng, const QRect& rect)
{
QScriptValue temp = eng->newObject();
temp.setProperty("x", rect.x());
temp.setProperty("y", rect.y());
temp.setProperty("width", rect.width());
temp.setProperty("height", rect.height());
return temp;
}
void Rect::fromScriptValue(const QScriptValue& obj, QRect &rect)
{
QScriptValue w = obj.property("w", QScriptValue::ResolveLocal);
QScriptValue h = obj.property("h", QScriptValue::ResolveLocal);
QScriptValue x = obj.property("x", QScriptValue::ResolveLocal);
QScriptValue y = obj.property("y", QScriptValue::ResolveLocal);
if(!w.isUndefined() && !h.isUndefined() && !x.isUndefined() && !y.isUndefined())
{
rect.setX(x.toInt32());
rect.setY(y.toInt32());
rect.setWidth(w.toInt32());
rect.setHeight(h.toInt32());
}
}
// End of meta for QRect object
// Other helper functions
void KWin::MetaScripting::registration(QScriptEngine* eng)
{
qScriptRegisterMetaType<KClientRef>(eng, Client::toScriptValue, Client::fromScriptValue);
qScriptRegisterMetaType<QPoint>(eng, Point::toScriptValue, Point::fromScriptValue);
qScriptRegisterMetaType<QSize>(eng, Size::toScriptValue, Size::fromScriptValue);
qScriptRegisterMetaType<QRect>(eng, Rect::toScriptValue, Rect::fromScriptValue);
qScriptRegisterMetaType<KToplevelRef>(eng, Toplevel::toScriptValue, Toplevel::fromScriptValue);
qScriptRegisterMetaType<KClientGroupRef>(eng, ClientGroup::toScriptValue, ClientGroup::fromScriptValue);
qScriptRegisterSequenceMetaType<QStringList>(eng);
qScriptRegisterSequenceMetaType< QList<KWin::ClientGroup*> >(eng);
qScriptRegisterSequenceMetaType<KClientList>(eng);
}
QScriptValue KWin::MetaScripting::configExists(QScriptContext* ctx, QScriptEngine* eng)
{
QHash<QString, QVariant> scriptConfig = (((ctx->thisObject()).data()).toVariant()).toHash();
QVariant val = scriptConfig.value((ctx->argument(0)).toString(), QVariant());
return eng->toScriptValue<bool>(val.isValid());
}
QScriptValue KWin::MetaScripting::getConfigValue(QScriptContext* ctx, QScriptEngine* eng)
{
int num = ctx->argumentCount();
QHash<QString, QVariant> scriptConfig = (((ctx->thisObject()).data()).toVariant()).toHash();
/*
* Handle config.get() seperately. Compute and return immediately.
**/
if(num == 0)
{
QHash<QString, QVariant>::const_iterator i;
QScriptValue ret = eng->newArray();
for(i = scriptConfig.constBegin(); i != scriptConfig.constEnd(); ++i)
{
ret.setProperty(i.key(), eng->newVariant(i.value()));
}
return ret;
}
if((num == 1) && !((ctx->argument(0)).isArray()))
{
QVariant val = scriptConfig.value((ctx->argument(0)).toString(), QVariant());
if(val.isValid())
{
return eng->newVariant(val);
}
else
{
return QScriptValue();
}
}
else
{
QScriptValue ret = eng->newArray();
int j = 0;
if((ctx->argument(0)).isArray())
{
bool simple = (num == 1)?0:(ctx->argument(1)).toBool();
QScriptValue array = (ctx->argument(0));
int len = (array.property("length").isValid())?array.property("length").toNumber():0;
for(int i=0; i<len; i++)
{
QVariant val = scriptConfig.value(array.property(i).toString(), QVariant());
if(val.isValid())
{
if(simple)
{
ret.setProperty(j, eng->newVariant(val));
}
else
{
ret.setProperty(array.property(i).toString(), eng->newVariant(val));
}
j++;
}
}
}
else
{
for(int i=0; i<num; i++)
{
QVariant val = scriptConfig.value((ctx->argument(i)).toString(), QVariant());
if(val.isValid())
{
ret.setProperty((ctx->argument(i)).toString(), eng->newVariant(val));
j = 1;
}
}
}
if(j == 0)
{
return QScriptValue();
}
else
{
return ret;
}
}
}
void KWin::MetaScripting::supplyConfig(QScriptEngine* eng, const QVariant& scriptConfig)
{
QScriptValue configObject = eng->newObject();
configObject.setData(eng->newVariant(scriptConfig));
configObject.setProperty("get", eng->newFunction(getConfigValue, 0), QScriptValue::Undeletable);
configObject.setProperty("exists", eng->newFunction(configExists, 0), QScriptValue::Undeletable);
configObject.setProperty("loaded", ((scriptConfig.toHash().empty())?eng->newVariant((bool)0):eng->newVariant((bool)1)), QScriptValue::Undeletable);
(eng->globalObject()).setProperty("config", configObject);
}
void KWin::MetaScripting::supplyConfig(QScriptEngine* eng)
{
KWin::MetaScripting::supplyConfig(eng, QVariant(QHash<QString, QVariant>()));
}
void KWin::MetaScripting::valueMerge(QScriptValue& first, QScriptValue second)
{
QScriptValueIterator value_it(second);
while(value_it.hasNext())
{
value_it.next();
first.setProperty(value_it.name(), value_it.value());
}
}
QScriptValue KWin::MetaScripting::getLazyLogicFunction(QScriptEngine* eng, const QString& type)
{
QScriptValue base = eng->newFunction(KWin::Chelate::lazyLogicGenerate, 0);
QScriptValue data = eng->newObject();
data.setProperty("lazylogic_type", eng->toScriptValue<QString>(type));
base.setData(data);
return base;
}

190
scripting/meta.h Normal file
View File

@ -0,0 +1,190 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef __KWIN__SCRIPTING_META_H
#define __KWIN__SCRIPTING_META_H
#include "client.h"
#include "s_clientgroup.h"
#include <QStringList>
#include <QScriptValueIterator>
typedef KWin::Client* KClientRef;
typedef KWin::ClientList KClientList;
typedef KWin::ClientGroup* KClientGroupRef;
typedef KWin::Toplevel* KToplevelRef;
namespace KWin
{
namespace Chelate
{
QScriptValue lazyLogicGenerate(QScriptContext*, QScriptEngine*);
};
};
Q_DECLARE_METATYPE(KClientRef)
Q_DECLARE_METATYPE(QPoint)
Q_DECLARE_METATYPE(QSize)
Q_DECLARE_METATYPE(QRect)
Q_DECLARE_METATYPE(KClientList)
Q_DECLARE_METATYPE(KClientGroupRef)
Q_DECLARE_METATYPE(KToplevelRef)
Q_DECLARE_METATYPE(QList<KWin::ClientGroup*>)
namespace KWin
{
namespace MetaScripting
{
/**
* The toScriptValue and fromScriptValue functions used in qScriptRegisterMetaType.
* Conversion functions for KWin::Client*
*/
namespace Client
{
QScriptValue toScriptValue(QScriptEngine*, const KClientRef&);
void fromScriptValue(const QScriptValue&, KClientRef&);
}
/**
* The toScriptValue and fromScriptValue functions used in qScriptRegisterMetaType.
* Conversion functions for KWin::ClientGroup*
*/
namespace ClientGroup
{
QScriptValue toScriptValue(QScriptEngine*, const KClientGroupRef&);
void fromScriptValue(const QScriptValue&, KClientGroupRef&);
}
/**
* The toScriptValue and fromScriptValue functions used in qScriptRegisterMetaType.
* Conversion functions for KWin::Toplevel*
*/
namespace Toplevel
{
QScriptValue toScriptValue(QScriptEngine*, const KToplevelRef&);
void fromScriptValue(const QScriptValue&, KToplevelRef&);
}
/**
* The toScriptValue and fromScriptValue functions used in qScriptRegisterMetaType.
* Conversion functions for QPoint
*/
namespace Point
{
QScriptValue toScriptValue(QScriptEngine*, const QPoint&);
void fromScriptValue(const QScriptValue&, QPoint&);
}
/**
* The toScriptValue and fromScriptValue functions used in qScriptRegisterMetaType.
* Conversion functions for QSize
*/
namespace Size
{
QScriptValue toScriptValue(QScriptEngine*, const QSize&);
void fromScriptValue(const QScriptValue&, QSize&);
}
/**
* The toScriptValue and fromScriptValue functions used in qScriptRegisterMetaType.
* Conversion functions for QRect
* TODO: QRect conversions have to be linked from plasma as they provide a lot more
* features. As for QSize and QPoint, I don't really plan any such thing.
*/
namespace Rect
{
QScriptValue toScriptValue(QScriptEngine*, const QRect&);
void fromScriptValue(const QScriptValue&, QRect&);
}
/**
* The Reference wrapping used previously for storing pointers to objects that were
* wrapped. Can still be used for non-QObject converted QScriptValue's, but as of
* now, it is not in use anywhere.
*/
namespace RefWrapping
{
// Simple template class to wrap pointers within QScriptValue's
template<typename T> void embed(QScriptValue&, const T);
template<typename T> T extract(const QScriptValue&);
}
/**
* Merges the second QScriptValue in the first one.
*/
void valueMerge(QScriptValue&, QScriptValue);
/**
* Registers all the meta conversion to the provided QScriptEngine
*/
void registration(QScriptEngine* eng);
/**
* Get the kind of LazyLogic (tm) function you want
*/
QScriptValue getLazyLogicFunction(QScriptEngine*, const QString&);
/**
* Functions for the JS function objects, config.exists and config.get.
* Read scripting/IMPLIST for details on how they work
*/
QScriptValue configExists(QScriptContext*, QScriptEngine*);
QScriptValue getConfigValue(QScriptContext*, QScriptEngine*);
/**
* Provide a config object to the given QScriptEngine depending
* on the keys provided in the QVariant. The provided QVariant
* MUST returns (true) on isHash()
*/
void supplyConfig(QScriptEngine*, const QVariant&);
/**
* For engines whose scripts have no associated configuration.
*/
void supplyConfig(QScriptEngine*);
// RefWrapping may be used for objects who use pointer based scriptvalue
// storage, but do not use caching.
template <typename T>
void RefWrapping::embed(QScriptValue& value, const T datum)
{
QScriptEngine* eng = value.engine();
value.setData(qScriptValueFromValue(eng,
static_cast<void*>(
const_cast<T>(datum)
)
));
}
template <typename T>
T RefWrapping::extract(const QScriptValue& value)
{
T datum = static_cast<T>(qscriptvalue_cast<void*>(value.data()));
return datum;
}
}
}
/**
* Code linked from plasma for QTimer.
*/
QScriptValue constructTimerClass(QScriptEngine *eng);
#endif

363
scripting/plasma-backportglobal.h Executable file
View File

@ -0,0 +1,363 @@
/****************************************************************************
**
** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.
**
** This file is part of the plugins of the Qt Toolkit.
**
** This file may be used under the terms of the GNU General Public
** License version 2.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
** http://trolltech.com/products/qt/licenses/licensing/opensource/
**
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
** or contact the sales department at sales@trolltech.com.
**
** In addition, as a special exception, Trolltech gives you certain
** additional rights. These rights are described in the Trolltech GPL
** Exception version 1.0, which can be found at
** http://www.trolltech.com/products/qt/gplexception/ and in the file
** GPL_EXCEPTION.txt in this package.
**
** In addition, as a special exception, Trolltech, as the sole copyright
** holder for Qt Designer, grants users of the Qt/Eclipse Integration
** plug-in the right for the Qt/Eclipse Integration to link to
** functionality provided by Qt Designer and its related libraries.
**
** Trolltech reserves all rights not expressly granted herein.
**
** Trolltech ASA (c) 2007
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
#ifndef QTSCRIPTEXTENSIONS_GLOBAL_H
#define QTSCRIPTEXTENSIONS_GLOBAL_H
#include <QtCore/QSharedData>
#define DECLARE_SELF(Class, __fn__) \
Class* self = qscriptvalue_cast<Class*>(ctx->thisObject()); \
if (!self) { \
return ctx->throwError(QScriptContext::TypeError, \
QString::fromLatin1("%0.prototype.%1: this object is not a %0") \
.arg(#Class).arg(#__fn__)); \
}
#define DECLARE_SELF2(Class, __fn__, __ret__) \
Class* self = qscriptvalue_cast<Class*>(thisObject()); \
if (!self) { \
context()->throwError(QScriptContext::TypeError, \
QString::fromLatin1("%0.prototype.%1: this object is not a %0") \
.arg(#Class).arg(#__fn__)); \
return __ret__; \
}
#define ADD_METHOD(__p__, __f__) \
__p__.setProperty(#__f__, __p__.engine()->newFunction(__f__))
#define ADD_GET_METHOD(__p__, __get__) \
ADD_METHOD(__p__, __get__)
#define ADD_GET_SET_METHODS(__p__, __get__, __set__) \
do { \
ADD_METHOD(__p__, __get__); \
ADD_METHOD(__p__, __set__); \
} while (0);
#define ADD_CTOR_FUNCTION(__c__, __f__) ADD_METHOD(__c__, __f__)
#define ADD_ENUM_VALUE(__c__, __ns__, __v__) \
__c__.setProperty(#__v__, QScriptValue(__c__.engine(), __ns__::__v__))
#define BEGIN_DECLARE_METHOD(Class, __mtd__) \
static QScriptValue __mtd__(QScriptContext *ctx, QScriptEngine *eng) \
{ \
DECLARE_SELF(Class, __mtd__);
#define END_DECLARE_METHOD \
}
#define DECLARE_GET_METHOD(Class, __get__) \
BEGIN_DECLARE_METHOD(Class, __get__) { \
return qScriptValueFromValue(eng, self->__get__()); \
} END_DECLARE_METHOD
#define DECLARE_SET_METHOD(Class, T, __set__) \
BEGIN_DECLARE_METHOD(Class, __set__) { \
self->__set__(qscriptvalue_cast<T>(ctx->argument(0))); \
return eng->undefinedValue(); \
} END_DECLARE_METHOD
#define DECLARE_GET_SET_METHODS(Class, T, __get__, __set__) \
DECLARE_GET_METHOD(Class, /*T,*/ __get__) \
DECLARE_SET_METHOD(Class, T, __set__)
#define DECLARE_SIMPLE_GET_METHOD(Class, __get__) \
BEGIN_DECLARE_METHOD(Class, __get__) { \
return QScriptValue(eng, self->__get__()); \
} END_DECLARE_METHOD
#define DECLARE_SIMPLE_SET_METHOD(Class, ToType, __set__) \
BEGIN_DECLARE_METHOD(Class, __set__) { \
self->__set__(ctx->argument(0).ToType()); \
return eng->undefinedValue(); \
} END_DECLARE_METHOD
#define DECLARE_BOOLEAN_GET_METHOD(Class, __set__) \
DECLARE_SIMPLE_GET_METHOD(Class, __set__)
#define DECLARE_BOOLEAN_SET_METHOD(Class, __set__) \
DECLARE_SIMPLE_SET_METHOD(Class, toBoolean, __set__)
#define DECLARE_INT_GET_METHOD(Class, __set__) \
DECLARE_SIMPLE_GET_METHOD(Class, __set__)
#define DECLARE_INT_SET_METHOD(Class, __set__) \
DECLARE_SIMPLE_SET_METHOD(Class, toInt32, __set__)
#define DECLARE_NUMBER_GET_METHOD(Class, __set__) \
DECLARE_SIMPLE_GET_METHOD(Class, __set__)
#define DECLARE_NUMBER_SET_METHOD(Class, __set__) \
DECLARE_SIMPLE_SET_METHOD(Class, toNumber, __set__)
#define DECLARE_STRING_GET_METHOD(Class, __set__) \
DECLARE_SIMPLE_GET_METHOD(Class, __set__)
#define DECLARE_STRING_SET_METHOD(Class, __set__) \
DECLARE_SIMPLE_SET_METHOD(Class, toString, __set__)
#define DECLARE_QOBJECT_GET_METHOD(Class, __get__) \
BEGIN_DECLARE_METHOD(Class, __get__) { \
return eng->newQObject(self->__get__()); \
} END_DECLARE_METHOD
#define DECLARE_QOBJECT_SET_METHOD(Class, __set__) \
DECLARE_SIMPLE_SET_METHOD(Class, toQObject, __set__)
#define DECLARE_BOOLEAN_GET_SET_METHODS(Class, __get__, __set__) \
DECLARE_BOOLEAN_GET_METHOD(Class, __get__) \
DECLARE_BOOLEAN_SET_METHOD(Class, __set__)
#define DECLARE_NUMBER_GET_SET_METHODS(Class, __get__, __set__) \
DECLARE_NUMBER_GET_METHOD(Class, __get__) \
DECLARE_NUMBER_SET_METHOD(Class, __set__)
#define DECLARE_INT_GET_SET_METHODS(Class, __get__, __set__) \
DECLARE_INT_GET_METHOD(Class, __get__) \
DECLARE_INT_SET_METHOD(Class, __set__)
#define DECLARE_STRING_GET_SET_METHODS(Class, __get__, __set__) \
DECLARE_STRING_GET_METHOD(Class, __get__) \
DECLARE_STRING_SET_METHOD(Class, __set__)
#define DECLARE_QOBJECT_GET_SET_METHODS(Class, __get__, __set__) \
DECLARE_QOBJECT_GET_METHOD(Class, __get__) \
DECLARE_QOBJECT_SET_METHOD(Class, __set__)
#define DECLARE_VOID_METHOD(Class, __fun__) \
BEGIN_DECLARE_METHOD(Class, __fun__) { \
self->__fun__(); \
return eng->undefinedValue(); \
} END_DECLARE_METHOD
#define DECLARE_VOID_NUMBER_METHOD(Class, __fun__) \
BEGIN_DECLARE_METHOD(Class, __fun__) { \
self->__fun__(ctx->argument(0).toNumber()); \
return eng->undefinedValue(); \
} END_DECLARE_METHOD
#define DECLARE_VOID_NUMBER_NUMBER_METHOD(Class, __fun__) \
BEGIN_DECLARE_METHOD(Class, __fun__) { \
self->__fun__(ctx->argument(0).toNumber(), ctx->argument(1).toNumber()); \
return eng->undefinedValue(); \
} END_DECLARE_METHOD
#define DECLARE_VOID_QUAD_NUMBER_METHOD(Class, __fun__) \
BEGIN_DECLARE_METHOD(Class, __fun__) { \
self->__fun__(ctx->argument(0).toNumber(), ctx->argument(1).toNumber(), ctx->argument(2).toNumber(), ctx->argument(3).toNumber()); \
return eng->undefinedValue(); \
} END_DECLARE_METHOD
#define DECLARE_VOID_1ARG_METHOD(Class, ArgType, __fun__) \
BEGIN_DECLARE_METHOD(Class, __fun__) { \
self->__fun__(qscriptvalue_cast<ArgType>(ctx->argument(0))); \
return eng->undefinedValue(); \
} END_DECLARE_METHOD
#define DECLARE_BOOLEAN_1ARG_METHOD(Class, ArgType, __fun__) \
BEGIN_DECLARE_METHOD(Class, __fun__) { \
return QScriptValue(eng, self->__fun__(qscriptvalue_cast<ArgType>(ctx->argument(0)))); \
} END_DECLARE_METHOD
#define DECLARE_POINTER_METATYPE(T) \
Q_DECLARE_METATYPE(T*) \
Q_DECLARE_METATYPE(QScript::Pointer<T>::wrapped_pointer_type)
namespace QScript
{
enum {
UserOwnership = 1
};
template <typename T>
class Pointer : public QSharedData
{
public:
typedef T* pointer_type;
typedef QExplicitlySharedDataPointer<Pointer<T> > wrapped_pointer_type;
~Pointer()
{
if (!(m_flags & UserOwnership))
delete m_value;
}
operator T*()
{
return m_value;
}
operator const T*() const
{
return m_value;
}
static wrapped_pointer_type create(T *value, uint flags = 0)
{
return wrapped_pointer_type(new Pointer(value, flags));
}
static QScriptValue toScriptValue(QScriptEngine *engine, T* const &source)
{
if (!source)
return engine->nullValue();
return engine->newVariant(qVariantFromValue(source));
}
static void fromScriptValue(const QScriptValue &value, T* &target)
{
if (value.isVariant()) {
QVariant var = value.toVariant();
if (qVariantCanConvert<T*>(var)) {
target = qvariant_cast<T*>(var);
} else if (qVariantCanConvert<wrapped_pointer_type>(var)) {
target = qvariant_cast<wrapped_pointer_type>(var)->operator T*();
} else {
// look in prototype chain
target = 0;
int type = qMetaTypeId<T*>();
int pointerType = qMetaTypeId<wrapped_pointer_type>();
QScriptValue proto = value.prototype();
while (proto.isObject() && proto.isVariant()) {
int protoType = proto.toVariant().userType();
if ((type == protoType) || (pointerType == protoType)) {
QByteArray name = QMetaType::typeName(var.userType());
if (name.startsWith("QScript::Pointer<")) {
target = (*reinterpret_cast<wrapped_pointer_type*>(var.data()))->operator T*();
break;
} else {
target = static_cast<T*>(var.data());
break;
}
}
proto = proto.prototype();
}
}
} else if (value.isQObject()) {
QObject *qobj = value.toQObject();
QByteArray typeName = QMetaType::typeName(qMetaTypeId<T*>());
target = reinterpret_cast<T*>(qobj->qt_metacast(typeName.left(typeName.size()-1)));
} else {
target = 0;
}
}
uint flags() const
{ return m_flags; }
void setFlags(uint flags)
{ m_flags = flags; }
void unsetFlags(uint flags)
{ m_flags &= ~flags; }
protected:
Pointer(T* value, uint flags)
: m_flags(flags), m_value(value)
{}
private:
uint m_flags;
T* m_value;
};
template <typename T>
int registerPointerMetaType(
QScriptEngine *eng,
const QScriptValue &prototype = QScriptValue(),
T * /* dummy */ = 0
)
{
QScriptValue (*mf)(QScriptEngine *, T* const &) = Pointer<T>::toScriptValue;
void (*df)(const QScriptValue &, T* &) = Pointer<T>::fromScriptValue;
const int id = qMetaTypeId<T*>();
qScriptRegisterMetaType_helper(
eng, id, reinterpret_cast<QScriptEngine::MarshalFunction>(mf),
reinterpret_cast<QScriptEngine::DemarshalFunction>(df),
prototype);
eng->setDefaultPrototype(qMetaTypeId<typename Pointer<T>::wrapped_pointer_type>(), prototype);
return id;
}
inline void maybeReleaseOwnership(const QScriptValue &value)
{
if (value.isVariant()) {
QVariant var = value.toVariant();
QByteArray name = QMetaType::typeName(var.userType());
if (name.startsWith("QScript::Pointer<"))
(*reinterpret_cast<Pointer<void*>::wrapped_pointer_type *>(var.data()))->setFlags(UserOwnership);
}
}
inline void maybeTakeOwnership(const QScriptValue &value)
{
if (value.isVariant()) {
QVariant var = value.toVariant();
QByteArray name = QMetaType::typeName(var.userType());
if (name.startsWith("QScript::Pointer<"))
(*reinterpret_cast<Pointer<void*>::wrapped_pointer_type *>(var.data()))->unsetFlags(UserOwnership);
}
}
template <class T>
inline QScriptValue wrapPointer(QScriptEngine *eng, T *ptr, uint flags = 0)
{
return eng->newVariant(qVariantFromValue(Pointer<T>::create(ptr, flags)));
}
} // namespace QScript
#ifdef QGRAPHICSITEM_H
namespace QScript {
template <class T>
inline QScriptValue wrapGVPointer(QScriptEngine *eng, T *item)
{
uint flags = item->parentItem() ? UserOwnership : 0;
return wrapPointer<T>(eng, item, flags);
}
} // namespace QScript
#endif // QGRAPHICSITEM_H
#endif // QTSCRIPTEXTENSIONS_GLOBAL_H

366
scripting/s_clientgroup.cpp Normal file
View File

@ -0,0 +1,366 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "s_clientgroup.h"
Q_DECLARE_METATYPE(SWrapper::ClientGroup*)
SWrapper::ClientGroup::ClientGroup(KWin::ClientGroup* group)
{
centralObject = group;
if(group == 0)
{
invalid = true;
}
else
{
setParent(group);
invalid = false;
}
}
SWrapper::ClientGroup::ClientGroup(KWin::Client* client)
{
if(client == 0)
{
invalid = true;
centralObject = 0;
return;
}
KWin::ClientGroup* cGrp = client->clientGroup();
if(cGrp == 0)
{
cGrp = new KWin::ClientGroup(client);
}
centralObject = cGrp;
setParent(cGrp);
invalid = false;
}
KWin::ClientGroup* SWrapper::ClientGroup::getCentralObject()
{
return centralObject;
}
/*
* This was just to check how bindings were working..
* Nothing to see here
*
QScriptValue SWrapper::ClientGroup::toString(QScriptContext* ctx, QScriptEngine* eng) {
SWrapper::ClientGroup* self = qscriptvalue_cast<SWrapper::ClientGroup*>(ctx->thisObject());
qDebug()<<"Generic object at ["<<(void*)self<<"]";
if(self != 0) {
qDebug()<<" Wrapping: ["<<(void*)(self->centralObject)<<"] (i: "<<self->invalid<<")";
}
return QScriptValue(eng, QString("."));
}
*/
QScriptValue SWrapper::ClientGroup::add(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Client* client = qscriptvalue_cast<KWin::Client*>(ctx->argument(0));
KWin::ClientGroup* cGrp = qscriptvalue_cast<KWin::ClientGroup*>(ctx->thisObject());
if((client == 0) || (cGrp == 0))
{
return QScriptValue(eng, (bool)0);
}
else
{
int before = (ctx->argument(1)).isUndefined()?(-1):((ctx->argument(0)).toNumber());
bool becomeVisible = (ctx->argument(2)).isUndefined()?(false):((ctx->argument(0)).toBool());
if(client->clientGroup())
{
(client->clientGroup())->remove(client);
}
cGrp->add(client, before, becomeVisible);
return QScriptValue(eng, (bool)1);
}
}
QScriptValue SWrapper::ClientGroup::remove(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::ClientGroup* cGrp = qscriptvalue_cast<KWin::ClientGroup*>(ctx->thisObject());
QScriptValue arg = ctx->argument(0);
QRect geom = eng->fromScriptValue<QRect>(ctx->argument(1));
if(cGrp == 0)
{
return eng->toScriptValue<bool>(0);
}
if(arg.isNumber())
{
cGrp->remove(arg.toNumber(), geom, false);
return eng->toScriptValue<bool>(1);
}
else
{
KWin::Client* client = qscriptvalue_cast<KWin::Client*>(arg);
if(client == 0)
{
return eng->toScriptValue<bool>(0);
}
else
{
cGrp->remove(client, geom, false);
return eng->toScriptValue<bool>(1);
}
}
}
QScriptValue SWrapper::ClientGroup::contains(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::ClientGroup* cGrp = qscriptvalue_cast<KWin::ClientGroup*>(ctx->thisObject());
if(cGrp == 0)
{
return QScriptValue();
}
else
{
KWin::Client* client = qscriptvalue_cast<KWin::Client*>(ctx->argument(0));
if(client == 0)
{
return QScriptValue();
}
else
{
return eng->toScriptValue<bool>(cGrp->contains(client));
}
}
}
QScriptValue SWrapper::ClientGroup::indexOf(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::ClientGroup* cGrp = qscriptvalue_cast<KWin::ClientGroup*>(ctx->thisObject());
if(cGrp == 0)
{
return QScriptValue();
}
else
{
KWin::Client* client = qscriptvalue_cast<KWin::Client*>(ctx->argument(0));
if(client == 0)
{
return QScriptValue();
}
else
{
return eng->toScriptValue<int>(cGrp->indexOfClient(client));
}
}
}
QScriptValue SWrapper::ClientGroup::move(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::ClientGroup* cGrp = qscriptvalue_cast<KWin::ClientGroup*>(ctx->thisObject());
// This is one weird function. It can be called like:
// move(client, client) OR move(client, index) OR move(index, client)
// move(index, index)
// NOTE: other than move(client, client), all other calls are mapped to
// move(index, index) using indexof(client)
QScriptValue arg1 = ctx->argument(0);
QScriptValue arg2 = ctx->argument(1);
KWin::Client* cl1 = qscriptvalue_cast<KWin::Client*>(arg1);
KWin::Client* cl2 = qscriptvalue_cast<KWin::Client*>(arg2);
if(cl1 != 0)
{
if(cl2 == 0)
{
if(!(arg2.isNumber()))
{
return eng->toScriptValue<bool>(0);
}
else
{
cGrp->move(cGrp->indexOfClient(cl1), (int)arg2.toNumber());
return eng->toScriptValue<bool>(1);
}
}
else
{
cGrp->move(cl1, cl2);
return eng->toScriptValue<bool>(1);
}
}
else
{
if(!(arg1.isNumber()))
{
return eng->toScriptValue<bool>(0);
}
else
{
if(cl2 != 0)
{
cGrp->move((int)arg1.toNumber(), cGrp->indexOfClient(cl2));
return eng->toScriptValue<bool>(1);
}
else
{
if(!arg2.isNumber())
{
return eng->toScriptValue<bool>(0);
}
else
{
cGrp->move((int)arg1.toNumber(), (int)arg2.toNumber());
return eng->toScriptValue<bool>(0);
}
}
}
}
}
QScriptValue SWrapper::ClientGroup::removeAll(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::ClientGroup* cGrp = qscriptvalue_cast<KWin::ClientGroup*>(ctx->thisObject());
if(cGrp == 0)
{
return eng->toScriptValue<bool>(0);
}
else
{
cGrp->removeAll();
return eng->toScriptValue<bool>(1);
}
}
QScriptValue SWrapper::ClientGroup::closeAll(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::ClientGroup* cGrp = qscriptvalue_cast<KWin::ClientGroup*>(ctx->thisObject());
if(cGrp == 0)
{
return eng->toScriptValue<bool>(0);
}
else
{
cGrp->closeAll();
return eng->toScriptValue<bool>(1);
}
}
QScriptValue SWrapper::ClientGroup::minSize(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::ClientGroup* cGrp = qscriptvalue_cast<KWin::ClientGroup*>(ctx->thisObject());
if(cGrp == 0)
{
return QScriptValue();
}
else
{
return eng->toScriptValue<QSize>(cGrp->minSize());
}
}
QScriptValue SWrapper::ClientGroup::maxSize(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::ClientGroup* cGrp = qscriptvalue_cast<KWin::ClientGroup*>(ctx->thisObject());
if(cGrp == 0)
{
return QScriptValue();
}
else
{
return eng->toScriptValue<QSize>(cGrp->maxSize());
}
}
QScriptValue SWrapper::ClientGroup::clients(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::ClientGroup* cGrp = qscriptvalue_cast<KWin::ClientGroup*>(ctx->thisObject());
if(cGrp == 0)
{
return QScriptValue();
}
else
{
return eng->toScriptValue<KClientList>(cGrp->clients());
}
}
QScriptValue SWrapper::ClientGroup::visible(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::ClientGroup* cGrp = qscriptvalue_cast<KWin::ClientGroup*>(ctx->thisObject());
if(cGrp == 0)
{
return QScriptValue();
}
else
{
return eng->toScriptValue<KWin::Client*>(cGrp->visible());
}
}
QScriptValue SWrapper::ClientGroup::generate(QScriptEngine* eng, SWrapper::ClientGroup* cGroup)
{
QScriptValue temp = eng->newQObject(cGroup, QScriptEngine::AutoOwnership);
temp.setProperty("add", eng->newFunction(add, 3), QScriptValue::Undeletable);
temp.setProperty("remove", eng->newFunction(remove, 1), QScriptValue::Undeletable);
temp.setProperty("clients", eng->newFunction(clients, 0), QScriptValue::Undeletable);
temp.setProperty("contains", eng->newFunction(contains, 1), QScriptValue::Undeletable);
temp.setProperty("indexOf", eng->newFunction(indexOf, 1), QScriptValue::Undeletable);
temp.setProperty("move", eng->newFunction(move, 2), QScriptValue::Undeletable);
temp.setProperty("removeAll", eng->newFunction(removeAll, 0), QScriptValue::Undeletable);
temp.setProperty("closeAll", eng->newFunction(closeAll, 0), QScriptValue::Undeletable);
temp.setProperty("minSize", eng->newFunction(minSize, 0), QScriptValue::Undeletable);
temp.setProperty("maxSize", eng->newFunction(maxSize, 0), QScriptValue::Undeletable);
temp.setProperty("visible", eng->newFunction(visible, 0), QScriptValue::Undeletable);
return temp;
}
QScriptValue SWrapper::ClientGroup::construct(QScriptContext* ctx, QScriptEngine* eng)
{
return generate(eng, new SWrapper::ClientGroup(
qscriptvalue_cast<KClientRef>(ctx->argument(0))
));
}
QScriptValue SWrapper::ClientGroup::publishClientGroupClass(QScriptEngine* eng)
{
QScriptValue proto = generate(eng, new SWrapper::ClientGroup((KWin::ClientGroup*)0));
eng->setDefaultPrototype(qMetaTypeId<SWrapper::ClientGroup*>(), proto);
return eng->newFunction(construct, proto);
}

77
scripting/s_clientgroup.h Normal file
View File

@ -0,0 +1,77 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef __KWIN__SCRIPTING_CLIENTGROUP_H
#define __KWIN__SCRIPTING_CLIENTGROUP_H
#include <QDebug>
#include <QScriptEngine>
#include "./../client.h"
#include "./../clientgroup.h"
namespace SWrapper
{
class ClientGroup : public QObject
{
Q_OBJECT
private:
KWin::ClientGroup* centralObject;
bool invalid;
public:
ClientGroup(KWin::ClientGroup*);
ClientGroup(KWin::Client*);
KWin::ClientGroup* getCentralObject();
/**
* A lot of functions for the KWin::ClientGroup* object.
* Mostly self-explanatory, works exactly like their C++
* analogues.
*/
static QScriptValue add(QScriptContext*, QScriptEngine*);
static QScriptValue remove(QScriptContext*, QScriptEngine*);
static QScriptValue clients(QScriptContext*, QScriptEngine*);
static QScriptValue setVisible(QScriptContext*, QScriptEngine*);
static QScriptValue contains(QScriptContext*, QScriptEngine*);
static QScriptValue indexOf(QScriptContext*, QScriptEngine*);
/** This is one weird function. It can be called like:
* move(client, client) OR move(client, index) OR move(index, client)
* move(index, index)
* NOTE: other than move(client, client), all other calls are mapped to
* move(index, index) using indexof(client)
*/
static QScriptValue move(QScriptContext*, QScriptEngine*);
static QScriptValue removeAll(QScriptContext*, QScriptEngine*);
static QScriptValue closeAll(QScriptContext*, QScriptEngine*);
static QScriptValue minSize(QScriptContext*, QScriptEngine*);
static QScriptValue maxSize(QScriptContext*, QScriptEngine*);
static QScriptValue visible(QScriptContext*, QScriptEngine*);
static QScriptValue construct(QScriptContext*, QScriptEngine*);
static QScriptValue generate(QScriptEngine*, SWrapper::ClientGroup*);
static QScriptValue publishClientGroupClass(QScriptEngine*);
};
}
#endif

128
scripting/scripting.cpp Normal file
View File

@ -0,0 +1,128 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include <kstandarddirs.h>
#include "scripting.h"
KWin::Scripting::Scripting()
{
// Default constructor no longer used, scripting can
// be disabled by calling kwin --noscript
}
void KWin::Scripting::start()
{
QStringList scriptFilters;
QString sDirectory = KStandardDirs::locateLocal("data", "kwin/scripts/");
if(sDirectory == "") {
// Abort scripting setup. No location found to locate scripts
return;
}
scriptFilters<<"*.kwinscript"<<"*.kws"<<"*.kwinqs";
scriptsDir.setPath(sDirectory);
scriptList = scriptsDir.entryList(scriptFilters, QDir::Files|QDir::Readable|QDir::Executable);
for(int i=0; i<scriptList.size(); i++)
{
scripts.append(new KWin::Script(new QScriptEngine(), scriptsDir.filePath(scriptList.at(i)), scriptsDir));
}
// Initialize singletons. Currently, only KWin::Workspace.
SWrapper::Workspace::initialize(KWin::Workspace::self());
runScripts();
}
void KWin::Scripting::runScript(KWin::Script* script)
{
if(script->scriptFile.open(QIODevice::ReadOnly))
{
script->workspace = new SWrapper::Workspace(script->engine);
(script->workspace)->attach(script->engine);
((script->engine)->globalObject()).setProperty("QTimer", constructTimerClass((script->engine)));
((script->engine)->globalObject()).setProperty("ClientGroup", SWrapper::ClientGroup::publishClientGroupClass((script->engine)));
((script->engine)->globalObject()).setProperty("chelate", KWin::Chelate::publishChelate(script->engine));
((script->engine)->globalObject()).setProperty("ch", KWin::Chelate::publishChelate(script->engine));
QObject::connect((script->engine), SIGNAL(signalHandlerException(const QScriptValue&)), this, SLOT(sigException(const QScriptValue&)));
KWin::MetaScripting::registration(script->engine);
if(scriptsDir.exists(script->configFile))
{
QSettings scriptSettings(scriptsDir.filePath(script->configFile), QSettings::IniFormat);
QHash<QString, QVariant> scriptConfig;
QStringList keys = scriptSettings.allKeys();
for(int i=0; i<keys.size(); i++)
{
scriptConfig.insert(keys.at(i), scriptSettings.value(keys.at(i)));
}
KWin::MetaScripting::supplyConfig(script->engine, QVariant(scriptConfig));
}
else
{
KWin::MetaScripting::supplyConfig(script->engine);
}
QScriptValue ret = (script->engine)->evaluate(QString((script->scriptFile).readAll()));
if(ret.isError())
{
sigException(ret);
}
}
}
void KWin::Scripting::runScripts()
{
for(int i=0; i<scripts.size(); i++)
{
runScript(scripts.at(i));
}
}
void KWin::Scripting::sigException(const QScriptValue& exception)
{
QScriptValue ret = exception;
if(ret.isError())
{
kDebug(1212)<<"defaultscript encountered an error at [Line "<<uncaughtExceptionLineNumber()<<"]";
kDebug(1212)<<"Message: "<<ret.toString();
kDebug(1212)<<"-----------------";
QScriptValueIterator iter(ret);
while(iter.hasNext())
{
iter.next();
qDebug()<<" "<<iter.name()<<": "<<iter.value().toString();
}
}
}
KWin::Scripting::~Scripting()
{
for(int i=0; i<scripts.size(); i++)
{
delete scripts.at(i);
}
}

106
scripting/scripting.h Normal file
View File

@ -0,0 +1,106 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef __KWIN__SCRIPTING_H_
#define __KWIN__SCRIPTING_H_
#include <QScriptClass>
#include <QScriptEngine>
#include <QDir>
#include <QVector>
#include <QSettings>
#include <QVariant>
#include "chelate.h"
#include "workspace.h"
#include "workspaceproxy.h"
#include "s_clientgroup.h"
#include "./../workspace.h"
#include "meta.h"
namespace KWin
{
/** This mostly behaves like a struct. Is used to store
* the scriptfile, the configfile and the QScriptEngine
* that will run this script
*/
class Script
{
public:
QScriptEngine* engine;
QFile scriptFile;
QString configFile;
SWrapper::Workspace* workspace;
Script(QScriptEngine* _engine, QString scriptName, QDir dir) :
engine(_engine)
{
scriptFile.setFileName(dir.filePath(scriptName));
configFile = (QFileInfo(scriptFile).completeBaseName() + QString(".kwscfg"));
}
~Script()
{
delete engine;
}
};
/**
* The heart of KWin::Scripting. Infinite power lies beyond
*/
class Scripting : public QScriptEngine
{
Q_OBJECT
private:
QStringList scriptList;
QDir scriptsDir;
QVector<KWin::Script*> scripts;
SWrapper::WorkspaceProxy proxy;
// Preferrably call ONLY at loadtime
void runScripts();
// NOTE: Runtime script running is not yet tested.
// Proceed with caution.
// An interface to run scripts at runtime
void runScript(KWin::Script*);
public slots:
/**
* A nice clean way to handle exceptions in scripting.
* TODO: Log to file, show from notifier..
*/
void sigException(const QScriptValue&);
public:
Scripting();
/**
* Start running scripts. This was essential to have KWin::Scripting
* be initialized on stack and also have the option to disable scripting.
*/
void start();
~Scripting();
};
}
#endif

70
scripting/timer.cpp Executable file
View File

@ -0,0 +1,70 @@
/*
* Copyright 2007 Richard J. Moore <rich@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License version 2 as
* published by the Free Software Foundation
*
* 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 Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <QtScript/QScriptValue>
#include <QtScript/QScriptEngine>
#include <QtScript/QScriptContext>
#include <QtScript/QScriptable>
#include <QtCore/QTimer>
#include "plasma-backportglobal.h"
Q_DECLARE_METATYPE(QTimer*)
static QScriptValue newTimer(QScriptEngine *eng, QTimer *timer)
{
return eng->newQObject(timer, QScriptEngine::AutoOwnership);
}
static QScriptValue ctor(QScriptContext *ctx, QScriptEngine *eng)
{
return newTimer(eng, new QTimer(qscriptvalue_cast<QObject*>(ctx->argument(0))));
}
static QScriptValue toString(QScriptContext *ctx, QScriptEngine *eng)
{
DECLARE_SELF(QTimer, toString);
return QScriptValue(eng, QString::fromLatin1("QTimer(interval=%0)")
.arg(self->interval()));
}
static QScriptValue active(QScriptContext *ctx, QScriptEngine *eng)
{
DECLARE_SELF(QTimer, active);
if (ctx->argumentCount()) {
if (ctx->argument(0).toBool()) {
self->start();
} else {
self->stop();
}
}
return QScriptValue(eng, self->isActive());
}
QScriptValue constructTimerClass(QScriptEngine *eng)
{
QScriptValue proto = newTimer(eng, new QTimer());
ADD_METHOD(proto, toString);
eng->setDefaultPrototype(qMetaTypeId<QTimer*>(), proto);
QScriptValue::PropertyFlags getter = QScriptValue::PropertyGetter;
QScriptValue::PropertyFlags setter = QScriptValue::PropertySetter;
proto.setProperty("active", eng->newFunction(active), getter | setter);
return eng->newFunction(ctor, proto);
}

113
scripting/toplevel.cpp Normal file
View File

@ -0,0 +1,113 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "toplevel.h"
Q_DECLARE_METATYPE(SWrapper::Toplevel*);
SWrapper::Toplevel::Toplevel(KWin::Toplevel* tlevel)
: QObject(tlevel)
{
tl_centralObject = 0;
}
KWin::Toplevel* SWrapper::Toplevel::extractClient(const QScriptValue& value)
{
SWrapper::Toplevel* tlevel = qscriptvalue_cast<SWrapper::Toplevel*>(value);
if(tlevel != 0)
{
return tlevel->tl_centralObject;
}
return 0;
}
MAP_GET(int, x)
MAP_GET(int, y)
MAP_GET(QSize, size)
MAP_GET(int, width)
MAP_GET(int, height)
MAP_GET(QRect, geometry)
MAP_GET(double, opacity)
MAP_GET(bool, hasAlpha)
QScriptValue SWrapper::Toplevel::pos(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Toplevel* central = extractClient(ctx->thisObject());
if(central == 0)
{
return QScriptValue();
}
else
{
return eng->toScriptValue(central->pos());
}
}
QScriptValue SWrapper::Toplevel::setOpacity(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::Toplevel* central = extractClient(ctx->thisObject());
if(central == 0)
{
return eng->toScriptValue<bool>(0);
}
else
{
QScriptValue opac = ctx->argument(0);
if(opac.isUndefined() || !opac.isNumber())
{
return eng->toScriptValue<bool>(0);
}
else
{
qsreal _opac = opac.toNumber();
// For some access restrictions, setting any window
// completely transperent is not allowed. As if, a window
// with 0.001 is perceptible. huh
if((_opac > 1) || (_opac <= 0))
{
return eng->toScriptValue<bool>(0);
}
else
{
central->setOpacity(_opac);
return eng->toScriptValue<bool>(1);
}
}
}
}
void SWrapper::Toplevel::tl_append(QScriptValue& value, QScriptEngine* eng)
{
QScriptValue func = eng->newFunction(pos, 0);
value.setProperty("pos", func, QScriptValue::Undeletable);
value.setProperty("x", eng->newFunction(x, 0), QScriptValue::Undeletable);
value.setProperty("y", eng->newFunction(y, 0), QScriptValue::Undeletable);
value.setProperty("size", eng->newFunction(size, 0), QScriptValue::Undeletable);
value.setProperty("width", eng->newFunction(width, 0), QScriptValue::Undeletable);
value.setProperty("height", eng->newFunction(height, 0), QScriptValue::Undeletable);
value.setProperty("geometry", eng->newFunction(geometry, 0), QScriptValue::Undeletable);
value.setProperty("opacity", eng->newFunction(opacity, 0), QScriptValue::Undeletable);
value.setProperty("hasAlpha", eng->newFunction(hasAlpha, 0), QScriptValue::Undeletable);
value.setProperty("setOpacity", eng->newFunction(setOpacity, 1), QScriptValue::Undeletable);
}

86
scripting/toplevel.h Normal file
View File

@ -0,0 +1,86 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef __KWIN__SCRIPTING_TOPLEVEL_H
#define __KWIN__SCRIPTING_TOPLEVEL_H
#include "./../toplevel.h"
#include <QObject>
#include <QScriptEngine>
#undef MAP_GET
#define MAP_GET(type, method) \
QScriptValue SWrapper::Toplevel::method(QScriptContext* ctx, QScriptEngine* eng) { \
KWin::Toplevel* central = extractClient(ctx->thisObject()); \
\
if(central == 0) { \
return QScriptValue(); \
} else { \
return eng->toScriptValue<type>(central->method()); \
} \
}
#define MAP_PROTO(method) static QScriptValue method(QScriptContext* ctx, QScriptEngine* eng);
#include <QDebug>
namespace SWrapper
{
class Toplevel : public QObject
{
Q_OBJECT
protected:
KWin::Toplevel* tl_centralObject;
private:
/**
* Naming abuse. Shoud've been extractToplevel, but let it just be
* for a while now :)
*/
static KWin::Toplevel* extractClient(const QScriptValue&);
public:
//generate a new QScriptValue constructed from a
//Toplevel object or any of it's derived classes
static void tl_append(QScriptValue&, QScriptEngine*);
static QScriptValue pos(QScriptContext* ctx, QScriptEngine* eng);
// No more properties
/**
* The various properties of KWin::Toplevel.
*/
MAP_PROTO(size)
MAP_PROTO(width)
MAP_PROTO(height)
MAP_PROTO(x)
MAP_PROTO(y)
MAP_PROTO(geometry)
MAP_PROTO(opacity)
MAP_PROTO(hasAlpha)
MAP_PROTO(setOpacity)
Toplevel(KWin::Toplevel*);
};
}
#endif

50
scripting/windowinfo.cpp Normal file
View File

@ -0,0 +1,50 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "windowinfo.h"
SWrapper::WindowInfo::WindowInfo(const KWindowInfo info, QScriptEngine* eng, QObject* parent) :
QObject(parent)
{
this->infoClass = info;
centralEngine = eng;
}
MAP_GET(valid, bool)
MAP_GET(state, int)
MAP_GET(isMinimized, bool)
MAP_GET(visibleName, QString)
MAP_GET2(windowClassClass, QString)
MAP_GET2(windowClassName, QString)
MAP_GET2(windowRole, QString)
QScriptValue SWrapper::WindowInfo::generate(const KWindowInfo info, QScriptEngine* eng, KWin::Client* client)
{
SWrapper::WindowInfo* winInfo = new SWrapper::WindowInfo(info, eng, static_cast<QObject*>(client));
QScriptValue temp = eng->newQObject(winInfo,
QScriptEngine::ScriptOwnership,
QScriptEngine::ExcludeSuperClassContents | QScriptEngine::ExcludeDeleteLater
);
KWin::MetaScripting::RefWrapping::embed<SWrapper::WindowInfo*>(temp, winInfo);
return temp;
}

97
scripting/windowinfo.h Normal file
View File

@ -0,0 +1,97 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef __KWIN__SCRIPTING_WINDOWINFO_H
#define __KWIN__SCRIPTING_WINDOWINFO_H
#include "./../client.h"
#include "meta.h"
#include <kwindowsystem.h>
#include <kwindowinfo.h>
#include <QScriptEngine>
// The following two extremely helpful functions are taken
// from the KWin Scripting proof-of-concept submitted by
// Lubos Lunak <l.lunak@kde.org>. Copyrights belong with
// original author (Lubos Lunak).
#undef MAP_GET
#undef MAP_SET
#define MAP_GET2(name, type2) \
type2 SWrapper::WindowInfo::name() const { \
return type2(infoClass.name()); \
}
#define MAP_GET(name, type) \
type SWrapper::WindowInfo::name() const { \
return infoClass.name(); \
}
#define MAP_SET(name, type) \
void SWrapper::Toplevel::name(type value) { \
subObject->name(value); \
}
namespace SWrapper
{
// No signals/slots here, but the usage of properties
// would make things a breeze, so a QObject it is.
class WindowInfo : public QObject
{
Q_OBJECT
private:
KWindowInfo infoClass;
QScriptEngine* centralEngine;
/**
* The info about a lot of window properties enumerated from the
* client this windowinfo was generated from.
*/
Q_PROPERTY(bool valid READ valid)
Q_PROPERTY(int state READ state)
Q_PROPERTY(bool isMinimized READ isMinimized)
Q_PROPERTY(QString visibleName READ visibleName)
Q_PROPERTY(QString windowClassClass READ windowClassClass)
Q_PROPERTY(QString windowClassName READ windowClassName)
Q_PROPERTY(QString windowRole READ windowRole)
bool valid() const;
int state() const;
bool isMinimized() const;
QString visibleName() const;
QString windowClassClass() const;
QString windowClassName() const;
QString windowRole() const;
public:
WindowInfo(const KWindowInfo, QScriptEngine*, QObject* parent = 0);
static QScriptValue generate(const KWindowInfo, QScriptEngine*, KWin::Client* client = 0);
};
}
#endif

350
scripting/workspace.cpp Normal file
View File

@ -0,0 +1,350 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "workspace.h"
#include "meta.h"
KWin::Workspace* SWrapper::Workspace::centralObject = 0;
SWrapper::Client* SWrapper::Workspace::clientHolder = 0;
SWrapper::Workspace::Workspace(QObject* parent) : QObject(parent)
{
if(centralObject == 0)
{
return;
}
else
{
SWrapper::WorkspaceProxy* proxy = SWrapper::WorkspaceProxy::instance();
QObject::connect(centralObject, SIGNAL(desktopPresenceChanged(KWin::Client*, int)),
this, SLOT(sl_desktopPresenceChanged(KWin::Client*, int))
);
QObject::connect(centralObject, SIGNAL(currentDesktopChanged(int)),
this, SLOT(sl_currentDesktopChanged(int))
);
QObject::connect(centralObject, SIGNAL(clientAdded(KWin::Client*)),
this, SLOT(sl_clientAdded(KWin::Client*))
);
QObject::connect(centralObject, SIGNAL(clientRemoved(KWin::Client*)),
this, SLOT(sl_clientRemoved(KWin::Client*))
);
QObject::connect(centralObject, SIGNAL(clientActivated(KWin::Client*)),
this, SLOT(sl_clientActivated(KWin::Client*))
);
QObject::connect(centralObject, SIGNAL(groupAdded(KWin::Group*)),
this, SLOT(sl_groupAdded(KWin::Group*))
);
QObject::connect(proxy, SIGNAL(clientMinimized(KWin::Client*)),
this, SLOT(sl_clientMinimized(KWin::Client*))
);
QObject::connect(proxy, SIGNAL(clientUnminimized(KWin::Client*)),
this, SLOT(sl_clientUnminimized(KWin::Client*))
);
QObject::connect(proxy, SIGNAL(clientMaximizeSet(KWin::Client*, QPair<bool, bool>)),
this, SLOT(sl_clientMaximizeSet(KWin::Client*, QPair<bool, bool>))
);
QObject::connect(proxy, SIGNAL(clientManaging(KWin::Client*)),
this, SLOT(sl_clientManaging(KWin::Client*))
);
QObject::connect(proxy, SIGNAL(killWindowCalled(KWin::Client*)),
this, SLOT(sl_killWindowCalled(KWin::Client*))
);
QObject::connect(proxy, SIGNAL(clientFullScreenSet(KWin::Client*, bool, bool)),
this, SLOT(sl_clientFullScreenSet(KWin::Client*, bool, bool))
);
}
}
void SWrapper::Workspace::sl_desktopPresenceChanged(KWin::Client* client, int prev_desk)
{
if(centralEngine == 0)
{
return;
}
else
{
emit desktopPresenceChanged(centralEngine->toScriptValue(client),
centralEngine->toScriptValue(prev_desk)
);
}
}
void SWrapper::Workspace::sl_clientAdded(KWin::Client* client)
{
if(centralEngine == 0)
{
return;
}
else
{
emit clientAdded(centralEngine->toScriptValue(client));
}
}
void SWrapper::Workspace::sl_clientFullScreenSet(KWin::Client* client, bool set, bool user)
{
if(centralEngine == 0)
{
return;
}
else
{
emit clientFullScreenSet(centralEngine->toScriptValue<KWin::Client*>(client),
centralEngine->toScriptValue<bool>(set),
centralEngine->toScriptValue<bool>(user)
);
}
}
void SWrapper::Workspace::sl_currentDesktopChanged(int prev_desk)
{
if(centralEngine == 0)
{
return;
}
else
{
emit currentDesktopChanged(centralEngine->toScriptValue(prev_desk));
}
}
void SWrapper::Workspace::sl_clientRemoved(KWin::Client* client)
{
if(centralEngine == 0)
{
return;
}
else
{
emit clientRemoved(centralEngine->toScriptValue(client));
}
}
void SWrapper::Workspace::sl_clientManaging(KWin::Client* client)
{
if(centralEngine == 0)
{
return;
}
else
{
emit clientManaging(centralEngine->toScriptValue(client));
}
}
void SWrapper::Workspace::sl_clientMinimized(KWin::Client* client)
{
if(centralEngine == 0)
{
return;
}
else
{
emit clientMinimized(centralEngine->toScriptValue(client));
}
}
void SWrapper::Workspace::sl_clientUnminimized(KWin::Client* client)
{
if(centralEngine == 0)
{
return;
}
else
{
emit clientUnminimized(centralEngine->toScriptValue<KWin::Client*>(client));
emit clientRestored(centralEngine->toScriptValue<KWin::Client*>(client));
}
}
void SWrapper::Workspace::sl_clientMaximizeSet(KWin::Client* client, QPair<bool, bool> param)
{
if(centralEngine == 0)
{
return;
}
else
{
QScriptValue temp = centralEngine->newObject();
temp.setProperty("v", centralEngine->toScriptValue(param.first));
temp.setProperty("h", centralEngine->toScriptValue(param.second));
emit clientMaximizeSet(centralEngine->toScriptValue(client), temp);
}
}
void SWrapper::Workspace::sl_killWindowCalled(KWin::Client* client)
{
if(centralEngine == 0)
{
return;
}
else
{
emit killWindowCalled(centralEngine->toScriptValue(client));
}
}
void SWrapper::Workspace::sl_clientActivated(KWin::Client* client)
{
if(centralEngine == 0)
{
return;
}
else
{
emit clientActivated(centralEngine->toScriptValue(client));
}
}
void SWrapper::Workspace::sl_groupAdded(KWin::Group* group)
{
Q_UNUSED(group);
//TODO
}
bool SWrapper::Workspace::initialize(KWin::Workspace* wspace)
{
if(wspace == 0)
{
return false;
}
else
{
SWrapper::Workspace::centralObject = wspace;
SWrapper::Workspace::clientHolder = new SWrapper::Client(0);
return true;
}
}
QScriptValue SWrapper::Workspace::getAllClients(QScriptContext* ctx, QScriptEngine* eng)
{
KWin::ClientList x = centralObject->stackingOrder();
if(ctx->argumentCount() == 0)
{
return eng->toScriptValue(x);
}
else
{
KWin::ClientList ret;
int desk_no = (ctx->argument(0)).toNumber();
if((desk_no >= 1) && (desk_no > SWrapper::Workspace::centralObject->numberOfDesktops()))
{
return QScriptValue();
}
else
{
for(int i=0; i<x.size(); i++)
{
if(x.at(i)->desktop() == desk_no)
{
ret.append(x.at(i));
}
}
return eng->toScriptValue(ret);
}
}
}
QScriptValue SWrapper::Workspace::activeClient(QScriptContext* ctx, QScriptEngine* eng)
{
Q_UNUSED(ctx);
return eng->toScriptValue<KWin::Client*>(centralObject->activeClient());
}
QScriptValue SWrapper::Workspace::setCurrentDesktop(QScriptContext* ctx, QScriptEngine* /*eng*/)
{
if(ctx->argumentCount() >= 1)
{
int num = ((ctx->argument(0)).isNumber())?((ctx->argument(0)).toNumber()):(-1);
if(num != -1)
{
centralObject->setCurrentDesktop(num);
}
}
return QScriptValue();
}
QScriptValue SWrapper::Workspace::dimensions(QScriptContext* ctx, QScriptEngine* eng)
{
Q_UNUSED(ctx);
return eng->toScriptValue(QSize(centralObject->workspaceWidth(), centralObject->workspaceHeight()));
}
QScriptValue SWrapper::Workspace::desktopGridSize(QScriptContext* ctx, QScriptEngine* eng)
{
Q_UNUSED(ctx);
return eng->toScriptValue(centralObject->desktopGridSize());
}
QScriptValue SWrapper::Workspace::clientGroups(QScriptContext* ctx, QScriptEngine* eng)
{
Q_UNUSED(ctx);
return eng->toScriptValue<QList<KWin::ClientGroup*> >(centralObject->clientGroups);
}
int SWrapper::Workspace::currentDesktop() const
{
return centralObject->currentDesktop();
}
void SWrapper::Workspace::attach(QScriptEngine* engine)
{
QScriptValue func;
centralEngine = engine;
QScriptValue self = engine->newQObject(
this,
QScriptEngine::QtOwnership,
QScriptEngine::ExcludeSuperClassContents | QScriptEngine::ExcludeDeleteLater
);
func = engine->newFunction(setCurrentDesktop, 1);
self.setProperty("setCurrentDesktop", func, QScriptValue::Undeletable);
func = engine->newFunction(getAllClients, 0);
self.setProperty("getAllClients", func, QScriptValue::Undeletable);
func = engine->newFunction(dimensions, 0);
self.setProperty("dimensions", func, QScriptValue::Undeletable);
func = engine->newFunction(desktopGridSize, 0);
self.setProperty("desktopGridSize", func, QScriptValue::Undeletable);
self.setProperty("activeClient", engine->newFunction(activeClient, 0), QScriptValue::Undeletable);
self.setProperty("clientGroups", engine->newFunction(clientGroups, 0), QScriptValue::Undeletable);
(engine->globalObject()).setProperty("workspace", self, QScriptValue::Undeletable);
}

95
scripting/workspace.h Normal file
View File

@ -0,0 +1,95 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef __KWIN__SCRIPTING_WORKSPACE_H
#define __KWIN__SCRIPTING_WORKSPACE_H
#include <QDebug>
#include "./../workspace.h"
#include "./../client.h"
#include "./../group.h"
#include "client.h"
#include "workspaceproxy.h"
#include <QScriptEngine>
namespace SWrapper
{
class Workspace : public QObject
{
Q_OBJECT
//Don't add WRITE for now. Access considerations
Q_PROPERTY( int currentDesktop READ currentDesktop );
private:
static KWin::Workspace* centralObject;
static SWrapper::Client* clientHolder;
QScriptEngine* centralEngine;
Q_DISABLE_COPY(Workspace);
public slots:
void sl_desktopPresenceChanged(KWin::Client*, int);
void sl_currentDesktopChanged(int);
void sl_clientAdded(KWin::Client*);
void sl_clientRemoved(KWin::Client*);
void sl_clientManaging(KWin::Client*);
void sl_clientMinimized(KWin::Client*);
void sl_clientUnminimized(KWin::Client*);
void sl_clientMaximizeSet(KWin::Client*, QPair<bool, bool>);
void sl_killWindowCalled(KWin::Client*);
void sl_clientActivated(KWin::Client*);
void sl_groupAdded(KWin::Group*);
void sl_clientFullScreenSet(KWin::Client*, bool, bool);
signals:
void desktopPresenceChanged(QScriptValue, QScriptValue);
void currentDesktopChanged(QScriptValue);
void clientAdded(QScriptValue);
void clientRemoved(QScriptValue);
void clientManaging(QScriptValue);
void clientMinimized(QScriptValue);
void clientUnminimized(QScriptValue);
void clientRestored(QScriptValue);
void clientMaximizeSet(QScriptValue, QScriptValue);
void killWindowCalled(QScriptValue);
void clientActivated(QScriptValue);
void clientFullScreenSet(QScriptValue, QScriptValue, QScriptValue);
public:
Workspace(QObject* parent = 0);
int currentDesktop() const;
void attach(QScriptEngine*);
static QScriptValue getAllClients(QScriptContext*, QScriptEngine*);
static bool initialize(KWin::Workspace*);
static QScriptValue setCurrentDesktop(QScriptContext*, QScriptEngine*);
static QScriptValue dimensions(QScriptContext*, QScriptEngine*);
static QScriptValue desktopGridSize(QScriptContext*, QScriptEngine*);
static QScriptValue activeClient(QScriptContext*, QScriptEngine*);
static QScriptValue clientGroups(QScriptContext*, QScriptEngine*);
};
};
#endif

View File

@ -0,0 +1,41 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "workspaceproxy.h"
SWrapper::WorkspaceProxy* SWrapper::WorkspaceProxy::_instance = 0;
SWrapper::WorkspaceProxy::WorkspaceProxy()
{
_instance = this;
}
SWrapper::WorkspaceProxy* SWrapper::WorkspaceProxy::instance()
{
return _instance;
}
PROXYPASS1(clientManaging, KWin::Client*)
PROXYPASS1(clientMinimized, KWin::Client*)
PROXYPASS1(clientUnminimized, KWin::Client*)
PROXYPASS1(killWindowCalled, KWin::Client*)
PROXYPASS2(clientMaximizeSet, KWin::Client*, DualBool)
PROXYPASS3(clientFullScreenSet, KWin::Client*, bool, bool)

View File

@ -0,0 +1,83 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef __KWIN_SCRIPTING_WORKSPACEPROXY_H_
#define __KWIN_SCRIPTING_WORKSPACEPROXY_H_
#include <QObject>
#include <QScriptValue>
#include <QDebug>
#include "../workspace.h"
#include "../client.h"
#define PROXYPASS1(name, param) \
void SWrapper::WorkspaceProxy::sl_ ## name(param _param) { \
name(_param); \
}
#define PROXYPASS2(name, param1, param2) \
void SWrapper::WorkspaceProxy::sl_ ## name(param1 _param1, param2 _param2) { \
name(_param1, _param2); \
}
#define PROXYPASS3(name, param1, param2, param3) \
void SWrapper::WorkspaceProxy::sl_ ## name(param1 _param1, param2 _param2, param3 _param3) { \
name(_param1, _param2, _param3); \
}
typedef QPair<bool, bool> DualBool;
namespace SWrapper
{
/**
* KWin::WorkspaceProxy simply allows connections from multiple clients to
* multiple Workspace objects.
*/
class WorkspaceProxy : public QObject
{
Q_OBJECT
public:
WorkspaceProxy();
static WorkspaceProxy* _instance;
static WorkspaceProxy* instance();
public slots:
void sl_clientManaging(KWin::Client*);
void sl_clientMinimized(KWin::Client*);
void sl_clientUnminimized(KWin::Client*);
void sl_clientMaximizeSet(KWin::Client*, QPair<bool, bool>);
void sl_killWindowCalled(KWin::Client*);
void sl_clientFullScreenSet(KWin::Client*, bool, bool);
signals:
void clientManaging(KWin::Client*);
void clientMinimized(KWin::Client*);
void clientUnminimized(KWin::Client*);
void clientMaximizeSet(KWin::Client*, QPair<bool, bool>);
void killWindowCalled(KWin::Client*);
void clientFullScreenSet(KWin::Client*, bool, bool);
};
};
#endif

View File

@ -59,6 +59,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "effects.h"
#include "tilinglayout.h"
#include "scripting/scripting.h"
#include <X11/extensions/shape.h>
#include <X11/keysym.h>
#include <X11/keysymdef.h>
@ -68,6 +70,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <kauthorized.h>
#include <ktoolinvocation.h>
#include <kglobalsettings.h>
#include <kwindowsystem.h>
#include <kwindowinfo.h>
#include <kephal/screens.h>
@ -594,6 +598,19 @@ Unmanaged* Workspace::createUnmanaged( Window w )
void Workspace::addClient( Client* c, allowed_t )
{
Group* grp = findGroup( c->window() );
KWindowInfo info = KWindowSystem::windowInfo(c->window(), -1U, NET::WM2WindowClass);
/*
if(info.windowClassName() == QString("krunner")) {
SWrapper::Workspace* ws_object = KWin::Scripting::workspace();
if(ws_object != 0) {
ws_object->sl_killWindowCalled(c);
}
}*/
emit clientAdded(c);
if( grp != NULL )
grp->gotLeader( c );
@ -645,6 +662,8 @@ void Workspace::addUnmanaged( Unmanaged* c, allowed_t )
*/
void Workspace::removeClient( Client* c, allowed_t )
{
emit clientRemoved(c);
if (c == active_popup_client)
closeActivePopup();
@ -1515,7 +1534,8 @@ bool Workspace::setCurrentDesktop( int new_desktop )
static_cast<EffectsHandlerImpl*>( effects )->desktopChanged( old_desktop );
if( compositing())
addRepaintFull();
emit currentDesktopChanged(old_desktop);
return true;
}
@ -1754,6 +1774,8 @@ void Workspace::sendClientToDesktop( Client* c, int desk, bool dont_activate )
if( c->desktop() != desk ) // No change or desktop forced
return;
desk = c->desktop(); // Client did range checking
emit desktopPresenceChanged(c, old_desktop);
if( c->isOnDesktop( currentDesktop() ))
{

View File

@ -765,6 +765,15 @@ class Workspace : public QObject, public KDecorationDefines
Q_SIGNALS:
Q_SCRIPTABLE void compositingToggled( bool active );
//Signals required for the scripting interface
signals:
void desktopPresenceChanged(KWin::Client*, int);
void currentDesktopChanged(int);
void clientAdded(KWin::Client*);
void clientRemoved(KWin::Client*);
void clientActivated(KWin::Client*);
void groupAdded(KWin::Group*);
private:
void init();
@ -1177,6 +1186,7 @@ inline Client* Workspace::mostRecentlyActivatedClient() const
inline void Workspace::addGroup( Group* group, allowed_t )
{
emit groupAdded(group);
groups.append( group );
}