kill the c dir
This commit is contained in:
parent
474f689132
commit
a648c05a7a
40 changed files with 0 additions and 8241 deletions
|
@ -1,5 +0,0 @@
|
|||
ob3
|
||||
Makefile.in
|
||||
.libs
|
||||
.deps
|
||||
Makefile
|
|
@ -1,34 +0,0 @@
|
|||
localedir=$(datadir)/locale
|
||||
scriptdir = $(libdir)/openbox/python
|
||||
|
||||
CPPFLAGS=$(PYTHON_CFLAGS) $(GLIB_CFLAGS) @CPPFLAGS@ \
|
||||
-DLOCALEDIR=\"$(localedir)\" \
|
||||
-DSCRIPTDIR=\"$(scriptdir)\" \
|
||||
-DG_LOG_DOMAIN=\"Openbox\"
|
||||
|
||||
LIBS=$(PYTHON_LIBS) $(GLIB_LIBS) @LIBS@
|
||||
|
||||
bin_PROGRAMS= ob3
|
||||
|
||||
ob3_LDADD=@LIBINTL@
|
||||
ob3_LDFLAGS=-export-dynamic
|
||||
ob3_SOURCES=client.c event.c extensions.c focus.c frame.c openbox.c prop.c \
|
||||
python.c screen.c stacking.c xerror.c hooks.c eventdata.c obexport.c \
|
||||
clientwrap.c screenwrap.c kbind.c mbind.c
|
||||
|
||||
noinst_HEADERS=client.h event.h extensions.h focus.h frame.h geom.h gettext.h \
|
||||
openbox.h prop.h python.h screen.h stacking.h xerror.h hooks.h \
|
||||
eventdata.h clientwrap.h obexport.h screenwrap.h kbind.h mbind.h
|
||||
|
||||
MAINTAINERCLEANFILES= Makefile.in
|
||||
|
||||
#if CVS
|
||||
#ob3.i: $(wildcard *.h)
|
||||
# @touch $@
|
||||
|
||||
#ob3_wrap.c: ob3.i
|
||||
# $(SWIG) $(SWIG_PYTHON_OPT) $(filter -I%,$(CPPFLAGS)) -o $@ $<
|
||||
#endif
|
||||
|
||||
distclean-local:
|
||||
$(RM) *\~ *.orig *.rej .\#*
|
1869
c/client.c
1869
c/client.c
File diff suppressed because it is too large
Load diff
401
c/client.h
401
c/client.h
|
@ -1,401 +0,0 @@
|
|||
#ifndef __client_h
|
||||
#define __client_h
|
||||
|
||||
#include "geom.h"
|
||||
#include "obexport.h"
|
||||
#include <glib.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
struct ClientWrap;
|
||||
struct Frame;
|
||||
|
||||
|
||||
/*! Holds an icon in ARGB format */
|
||||
typedef struct Icon {
|
||||
unsigned long w, h;
|
||||
unsigned long *data;
|
||||
} Icon;
|
||||
|
||||
/*! The MWM Hints as retrieved from the window property
|
||||
This structure only contains 3 elements, even though the Motif 2.0
|
||||
structure contains 5. We only use the first 3, so that is all gets
|
||||
defined.
|
||||
*/
|
||||
typedef struct MwmHints {
|
||||
/*! A bitmask of Client::MwmFlags values */
|
||||
unsigned long flags;
|
||||
/*! A bitmask of Client::MwmFunctions values */
|
||||
unsigned long functions;
|
||||
/*! A bitmask of Client::MwmDecorations values */
|
||||
unsigned long decorations;
|
||||
} MwmHints;
|
||||
/*! The number of elements in the Client::MwmHints struct */
|
||||
#define MWM_ELEMENTS 3
|
||||
|
||||
/*! Possible flags for MWM Hints (defined by Motif 2.0) */
|
||||
typedef enum {
|
||||
MwmFlag_Functions = 1 << 0, /*!< The MMW Hints define funcs */
|
||||
MwmFlag_Decorations = 1 << 1 /*!< The MWM Hints define decor */
|
||||
} MwmFlags;
|
||||
|
||||
/*! Possible functions for MWM Hints (defined by Motif 2.0) */
|
||||
typedef enum {
|
||||
MwmFunc_All = 1 << 0, /*!< All functions */
|
||||
MwmFunc_Resize = 1 << 1, /*!< Allow resizing */
|
||||
MwmFunc_Move = 1 << 2, /*!< Allow moving */
|
||||
MwmFunc_Iconify = 1 << 3, /*!< Allow to be iconfied */
|
||||
MwmFunc_Maximize = 1 << 4 /*!< Allow to be maximized */
|
||||
/*MwmFunc_Close = 1 << 5 /!< Allow to be closed */
|
||||
} MwmFunctions;
|
||||
|
||||
/*! Possible decorations for MWM Hints (defined by Motif 2.0) */
|
||||
typedef enum {
|
||||
MwmDecor_All = 1 << 0, /*!< All decorations */
|
||||
MwmDecor_Border = 1 << 1, /*!< Show a border */
|
||||
MwmDecor_Handle = 1 << 2, /*!< Show a handle (bottom) */
|
||||
MwmDecor_Title = 1 << 3, /*!< Show a titlebar */
|
||||
/*MwmDecor_Menu = 1 << 4, /!< Show a menu */
|
||||
MwmDecor_Iconify = 1 << 5, /*!< Show an iconify button */
|
||||
MwmDecor_Maximize = 1 << 6 /*!< Show a maximize button */
|
||||
} MemDecorations;
|
||||
|
||||
|
||||
typedef struct Client {
|
||||
Window window;
|
||||
|
||||
struct Frame *frame;
|
||||
|
||||
/*! The number of unmap events to ignore on the window */
|
||||
int ignore_unmaps;
|
||||
|
||||
/*! The id of the group the window belongs to */
|
||||
Window group;
|
||||
/*! Whether or not the client is a transient window. This is guaranteed to
|
||||
be TRUE if transient_for != NULL, but not guaranteed to be FALSE if
|
||||
transient_for == NULL. */
|
||||
gboolean transient;
|
||||
/*! The client which this client is a transient (child) for */
|
||||
struct Client *transient_for;
|
||||
/*! The clients which are transients (children) of this client */
|
||||
GSList *transients;
|
||||
/*! The desktop on which the window resides (0xffffffff for all
|
||||
desktops) */
|
||||
unsigned int desktop;
|
||||
|
||||
/*! Normal window title */
|
||||
gchar *title;
|
||||
/*! Window title when iconified */
|
||||
gchar *icon_title;
|
||||
|
||||
/*! The application that created the window */
|
||||
gchar *res_name;
|
||||
/*! The class of the window, can used for grouping */
|
||||
gchar *res_class;
|
||||
/*! The specified role of the window, used for identification */
|
||||
gchar *role;
|
||||
|
||||
/*! The type of window (what its function is) */
|
||||
WindowType type;
|
||||
|
||||
/*! Position and size of the window
|
||||
This will not always be the actual position of the window on screen, it
|
||||
is, rather, the position requested by the client, to which the window's
|
||||
gravity is applied.
|
||||
*/
|
||||
Rect area;
|
||||
|
||||
/*! The window's strut
|
||||
The strut defines areas of the screen that are marked off-bounds for
|
||||
window placement. In theory, where this window exists.
|
||||
*/
|
||||
Strut strut;
|
||||
|
||||
/*! The logical size of the window
|
||||
The "logical" size of the window is refers to the user's perception of
|
||||
the size of the window, and is the value that should be displayed to the
|
||||
user. For example, with xterms, this value it the number of characters
|
||||
being displayed in the terminal, instead of the number of pixels.
|
||||
*/
|
||||
Size logical_size;
|
||||
|
||||
/*! Width of the border on the window.
|
||||
The window manager will set this to 0 while the window is being managed,
|
||||
but needs to restore it afterwards, so it is saved here.
|
||||
*/
|
||||
guint border_width;
|
||||
|
||||
/*! The minimum aspect ratio the client window can be sized to.
|
||||
A value of 0 means this is ignored.
|
||||
*/
|
||||
float min_ratio;
|
||||
/*! The maximum aspect ratio the client window can be sized to.
|
||||
A value of 0 means this is ignored.
|
||||
*/
|
||||
float max_ratio;
|
||||
|
||||
/*! The minimum size of the client window
|
||||
If the min is > the max, then the window is not resizable
|
||||
*/
|
||||
Size min_size;
|
||||
/*! The maximum size of the client window
|
||||
If the min is > the max, then the window is not resizable
|
||||
*/
|
||||
Size max_size;
|
||||
/*! The size of increments to resize the client window by */
|
||||
Size size_inc;
|
||||
/*! The base size of the client window
|
||||
This value should be subtracted from the window's actual size when
|
||||
displaying its size to the user, or working with its min/max size
|
||||
*/
|
||||
Size base_size;
|
||||
|
||||
/*! Window decoration and functionality hints */
|
||||
MwmHints mwmhints;
|
||||
|
||||
/*! Where to place the decorated window in relation to the undecorated
|
||||
window */
|
||||
int gravity;
|
||||
|
||||
/*! The state of the window, one of WithdrawnState, IconicState, or
|
||||
NormalState */
|
||||
long wmstate;
|
||||
|
||||
/*! True if the client supports the delete_window protocol */
|
||||
gboolean delete_window;
|
||||
|
||||
/*! Was the window's position requested by the application? if not, we
|
||||
should place the window ourselves when it first appears */
|
||||
gboolean positioned;
|
||||
|
||||
/*! Can the window receive input focus? */
|
||||
gboolean can_focus;
|
||||
/*! Urgency flag */
|
||||
gboolean urgent;
|
||||
/*! Notify the window when it receives focus? */
|
||||
gboolean focus_notify;
|
||||
/*! Does the client window have the input focus? */
|
||||
gboolean focused;
|
||||
|
||||
/*! The window uses shape extension to be non-rectangular? */
|
||||
gboolean shaped;
|
||||
|
||||
/*! The window is modal, so it must be processed before any windows it is
|
||||
related to can be focused */
|
||||
gboolean modal;
|
||||
/*! Only the window's titlebar is displayed */
|
||||
gboolean shaded;
|
||||
/*! The window is iconified */
|
||||
gboolean iconic;
|
||||
/*! The window is maximized to fill the screen vertically */
|
||||
gboolean max_vert;
|
||||
/*! The window is maximized to fill the screen horizontally */
|
||||
gboolean max_horz;
|
||||
/*! The window should not be displayed by pagers */
|
||||
gboolean skip_pager;
|
||||
/*! The window should not be displayed by taskbars */
|
||||
gboolean skip_taskbar;
|
||||
/*! The window is a 'fullscreen' window, and should be on top of all
|
||||
others */
|
||||
gboolean fullscreen;
|
||||
/*! The window should be on top of other windows of the same type */
|
||||
gboolean above;
|
||||
/*! The window should be underneath other windows of the same type */
|
||||
gboolean below;
|
||||
|
||||
/*! The layer in which the window will be stacked, windows in lower layers
|
||||
are always below windows in higher layers. */
|
||||
StackLayer layer;
|
||||
|
||||
/*! A bitmask of values in the Decoration enum
|
||||
The values in the variable are the decorations that the client wants to
|
||||
be displayed around it.
|
||||
*/
|
||||
int decorations;
|
||||
|
||||
/*! A bitmask of values in the Decoration enum.
|
||||
Specifies the decorations that should NOT be displayed on the client.
|
||||
*/
|
||||
int disabled_decorations;
|
||||
|
||||
/*! A bitmask of values in the Function enum
|
||||
The values in the variable specify the ways in which the user is allowed
|
||||
to modify this window.
|
||||
*/
|
||||
int functions;
|
||||
|
||||
/*! Icons for the client as specified on the client window */
|
||||
Icon *icons;
|
||||
/*! The number of icons in icons */
|
||||
int nicons;
|
||||
|
||||
/*! The icon for the client specified in the WMHints or the KWM hints */
|
||||
Pixmap pixmap_icon;
|
||||
/*! The mask for the pixmap_icon, or None if its not masked */
|
||||
Pixmap pixmap_icon_mask;
|
||||
|
||||
/* The instance of the wrapper class if one exists */
|
||||
struct ClientWrap *wrap;
|
||||
} Client;
|
||||
|
||||
extern GSList *client_list;
|
||||
extern GHashTable *client_map;
|
||||
|
||||
void client_startup();
|
||||
void client_shutdown();
|
||||
|
||||
/*! Manages all existing windows */
|
||||
void client_manage_all();
|
||||
/*! Manages a given window */
|
||||
void client_manage(Window win);
|
||||
/*! Unmanages all managed windows */
|
||||
void client_unmanage_all();
|
||||
/*! Unmanages a given client */
|
||||
void client_unmanage(Client *client);
|
||||
|
||||
/*! Sets the client list on the root window from the client_list */
|
||||
void client_set_list();
|
||||
|
||||
/*! Reapplies the maximized state to the window
|
||||
Use this to make the window readjust its maximized size to new
|
||||
surroundings (struts, etc). */
|
||||
void client_remaximize(Client *self);
|
||||
|
||||
/*! Shows the window if it should be shown, or hides it
|
||||
Used when changing desktops, the window's state, etc. */
|
||||
void client_showhide(Client *self);
|
||||
|
||||
/*! Returns if the window should be treated as a normal window.
|
||||
Some windows (desktops, docks, splash screens) have special rules applied
|
||||
to them in a number of places regarding focus or user interaction. */
|
||||
gboolean client_normal(Client *self);
|
||||
|
||||
/*! Internal version of the Client::resize function
|
||||
This also maintains things like the client's minsize, and size increments.
|
||||
@param anchor The corner to keep in the same position when resizing.
|
||||
@param x The x coordiante of the new position for the client.
|
||||
@param y The y coordiante of the new position for the client.
|
||||
@param w The width component of the new size for the client.
|
||||
@param h The height component of the new size for the client.
|
||||
@param user Specifies whether this is a user-requested change or a
|
||||
program requested change. For program requested changes, the
|
||||
constraints are not checked.
|
||||
@param final If user is true, then this should specify if this is a final
|
||||
configuration. e.g. Final should be FALSE if doing an
|
||||
interactive move/resize, and then be TRUE for the last call
|
||||
only.
|
||||
*/
|
||||
void client_configure(Client *self, Corner anchor, int x, int y, int w, int h,
|
||||
gboolean user, gboolean final);
|
||||
|
||||
/*! Fullscreen's or unfullscreen's the client window
|
||||
@param fs true if the window should be made fullscreen; false if it should
|
||||
be returned to normal state.
|
||||
@param savearea true to have the client's current size and position saved;
|
||||
otherwise, they are not. You should not save when mapping a
|
||||
new window that is set to fullscreen. This has no effect
|
||||
when restoring a window from fullscreen.
|
||||
*/
|
||||
void client_fullscreen(Client *self, gboolean fs, gboolean savearea);
|
||||
|
||||
/*! Iconifies or uniconifies the client window
|
||||
@param iconic true if the window should be iconified; false if it should be
|
||||
restored.
|
||||
@param curdesk If iconic is FALSE, then this determines if the window will
|
||||
be uniconified to the current viewable desktop (true) or to
|
||||
its previous desktop (false)
|
||||
*/
|
||||
void client_iconify(Client *self, gboolean iconic, gboolean curdesk);
|
||||
|
||||
/*! Maximize or unmaximize the client window
|
||||
@param max true if the window should be maximized; false if it should be
|
||||
returned to normal size.
|
||||
@param dir 0 to set both horz and vert, 1 to set horz, 2 to set vert.
|
||||
@param savearea true to have the client's current size and position saved;
|
||||
otherwise, they are not. You should not save when mapping a
|
||||
new window that is set to fullscreen. This has no effect
|
||||
when unmaximizing a window.
|
||||
*/
|
||||
void client_maximize(Client *self, gboolean max, int dir,
|
||||
gboolean savearea);
|
||||
|
||||
/*! Shades or unshades the client window
|
||||
@param shade true if the window should be shaded; false if it should be
|
||||
unshaded.
|
||||
*/
|
||||
void client_shade(Client *self, gboolean shade);
|
||||
|
||||
/*! Request the client to close its window. */
|
||||
void client_close(Client *self);
|
||||
|
||||
/*! Sends the window to the specified desktop */
|
||||
void client_set_desktop(Client *self, unsigned int target);
|
||||
|
||||
/*! Return a modal child of the client window
|
||||
@return A modal child of the client window, or 0 if none was found.
|
||||
*/
|
||||
Client *client_find_modal_child(Client *self);
|
||||
|
||||
/*! Validate client, by making sure no Destroy or Unmap events exist in
|
||||
the event queue for the window.
|
||||
@return true if the client is valid; false if the client has already
|
||||
been unmapped/destroyed, and so is invalid.
|
||||
*/
|
||||
gboolean client_validate(Client *self);
|
||||
|
||||
/*! Sets the wm_state to the specified value */
|
||||
void client_set_wm_state(Client *self, long state);
|
||||
|
||||
/*! Adjusts the window's net_state
|
||||
This should not be called as part of the window mapping process! It is for
|
||||
use when updating the state post-mapping.<br>
|
||||
client_apply_startup_state is used to do the same things during the mapping
|
||||
process.
|
||||
*/
|
||||
void client_set_state(Client *self, Atom action, long data1, long data2);
|
||||
|
||||
/*! Attempt to focus the client window */
|
||||
gboolean client_focus(Client *self);
|
||||
|
||||
/*! Remove focus from the client window */
|
||||
void client_unfocus(Client *self);
|
||||
|
||||
/*! Calculates the stacking layer for the client window */
|
||||
void client_calc_layer(Client *self);
|
||||
|
||||
/*! Updates the window's transient status, and any parents of it */
|
||||
void client_update_transient_for(Client *self);
|
||||
/*! Update the protocols that the window supports and adjusts things if they
|
||||
change */
|
||||
void client_update_protocols(Client *self);
|
||||
/*! Updates the WMNormalHints and adjusts things if they change */
|
||||
void client_update_normal_hints(Client *self);
|
||||
|
||||
/*! Updates the WMHints and adjusts things if they change
|
||||
@param initstate Whether to read the initial_state property from the
|
||||
WMHints. This should only be used during the mapping
|
||||
process.
|
||||
*/
|
||||
void client_update_wmhints(Client *self);
|
||||
/*! Updates the window's title */
|
||||
void client_update_title(Client *self);
|
||||
/*! Updates the window's icon title */
|
||||
void client_update_icon_title(Client *self);
|
||||
/*! Updates the window's application name and class */
|
||||
void client_update_class(Client *self);
|
||||
/*! Updates the strut for the client */
|
||||
void client_update_strut(Client *self);
|
||||
/*! Updates the window's icons */
|
||||
void client_update_icons(Client *self);
|
||||
/*! Updates the window's kwm icon */
|
||||
void client_update_kwm_icon(Client *self);
|
||||
|
||||
/*! Set up what decor should be shown on the window and what functions should
|
||||
be allowed (Client::_decorations and Client::_functions).
|
||||
This also updates the NET_WM_ALLOWED_ACTIONS hint.
|
||||
*/
|
||||
void client_setup_decor_and_functions(Client *self);
|
||||
|
||||
/*! Retrieves the window's type and sets Client->type */
|
||||
void client_get_type(Client *self);
|
||||
|
||||
#endif
|
792
c/clientwrap.c
792
c/clientwrap.c
|
@ -1,792 +0,0 @@
|
|||
#include "clientwrap.h"
|
||||
#include "client.h"
|
||||
#include "frame.h"
|
||||
#include "stacking.h"
|
||||
#include "focus.h"
|
||||
#include <glib.h>
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Define the type 'ClientWrap'
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#define IS_CWRAP(v) ((v)->ob_type == &ClientWrapType)
|
||||
#define IS_VALID_CWRAP(v) ((v)->client != NULL)
|
||||
#define CHECK_CWRAP(self, funcname) { \
|
||||
if (!IS_CWRAP(self)) { \
|
||||
PyErr_SetString(PyExc_TypeError, \
|
||||
"descriptor '" funcname "' requires a 'Client' " \
|
||||
"object"); \
|
||||
return NULL; \
|
||||
} \
|
||||
if (!IS_VALID_CWRAP(self)) { \
|
||||
PyErr_SetString(PyExc_ValueError, \
|
||||
"This 'Client' is wrapping a client which no longer "\
|
||||
"exists."); \
|
||||
return NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
staticforward PyTypeObject ClientWrapType;
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Attribute methods
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
static PyObject *cwrap_window(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "window");
|
||||
if (!PyArg_ParseTuple(args, ":window"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->window);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_group(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "group");
|
||||
if (!PyArg_ParseTuple(args, ":group"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->group);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_parent(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "parent");
|
||||
if (!PyArg_ParseTuple(args, ":parent"))
|
||||
return NULL;
|
||||
if (self->client->transient_for != NULL)
|
||||
return clientwrap_new(self->client->transient_for);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *cwrap_children(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
PyObject *list;
|
||||
GSList *it;
|
||||
guint i, s;
|
||||
|
||||
CHECK_CWRAP(self, "children");
|
||||
if (!PyArg_ParseTuple(args, ":children"))
|
||||
return NULL;
|
||||
s = g_slist_length(self->client->transients);
|
||||
list = PyList_New(s);
|
||||
for (i = 0, it = self->client->transients; i < s; ++i, it = it->next)
|
||||
PyList_SET_ITEM(list, i, clientwrap_new(it->data));
|
||||
return list;
|
||||
}
|
||||
|
||||
static PyObject *cwrap_desktop(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "desktop");
|
||||
if (!PyArg_ParseTuple(args, ":desktop"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->desktop);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_title(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "title");
|
||||
if (!PyArg_ParseTuple(args, ":title"))
|
||||
return NULL;
|
||||
return PyString_FromString(self->client->title);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_iconTitle(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "iconTitle");
|
||||
if (!PyArg_ParseTuple(args, ":iconTitle"))
|
||||
return NULL;
|
||||
return PyString_FromString(self->client->icon_title);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_resName(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "resName");
|
||||
if (!PyArg_ParseTuple(args, ":resName"))
|
||||
return NULL;
|
||||
return PyString_FromString(self->client->res_name);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_resClass(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "resClass");
|
||||
if (!PyArg_ParseTuple(args, ":resClass"))
|
||||
return NULL;
|
||||
return PyString_FromString(self->client->res_class);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_role(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "role");
|
||||
if (!PyArg_ParseTuple(args, ":role"))
|
||||
return NULL;
|
||||
return PyString_FromString(self->client->role);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_type(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "type");
|
||||
if (!PyArg_ParseTuple(args, ":type"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->type);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_area(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
PyObject *tuple;
|
||||
|
||||
CHECK_CWRAP(self, "area");
|
||||
if (!PyArg_ParseTuple(args, ":area"))
|
||||
return NULL;
|
||||
tuple = PyTuple_New(4);
|
||||
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->client->area.x));
|
||||
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->client->area.y));
|
||||
PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(self->client->area.width));
|
||||
PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(self->client->area.height));
|
||||
return tuple;
|
||||
}
|
||||
|
||||
static PyObject *cwrap_screenArea(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
PyObject *tuple;
|
||||
|
||||
CHECK_CWRAP(self, "screenArea");
|
||||
if (!PyArg_ParseTuple(args, ":screenArea"))
|
||||
return NULL;
|
||||
tuple = PyTuple_New(4);
|
||||
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->client->frame->area.x));
|
||||
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->client->frame->area.y));
|
||||
PyTuple_SET_ITEM(tuple, 2,
|
||||
PyInt_FromLong(self->client->frame->area.width));
|
||||
PyTuple_SET_ITEM(tuple, 3,
|
||||
PyInt_FromLong(self->client->frame->area.height));
|
||||
return tuple;
|
||||
}
|
||||
|
||||
static PyObject *cwrap_strut(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
PyObject *tuple;
|
||||
|
||||
CHECK_CWRAP(self, "strut");
|
||||
if (!PyArg_ParseTuple(args, ":strut"))
|
||||
return NULL;
|
||||
tuple = PyTuple_New(4);
|
||||
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->client->strut.left));
|
||||
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->client->strut.top));
|
||||
PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(self->client->strut.right));
|
||||
PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(self->client->strut.bottom));
|
||||
return tuple;
|
||||
}
|
||||
|
||||
static PyObject *cwrap_logicalSize(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
PyObject *tuple;
|
||||
|
||||
CHECK_CWRAP(self, "logicalSize");
|
||||
if (!PyArg_ParseTuple(args, ":logicalSize"))
|
||||
return NULL;
|
||||
tuple = PyTuple_New(2);
|
||||
PyTuple_SET_ITEM(tuple, 0,
|
||||
PyInt_FromLong(self->client->logical_size.width));
|
||||
PyTuple_SET_ITEM(tuple, 1,
|
||||
PyInt_FromLong(self->client->logical_size.height));
|
||||
return tuple;
|
||||
}
|
||||
|
||||
static PyObject *cwrap_minRatio(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "minRatio");
|
||||
if (!PyArg_ParseTuple(args, ":minRatio"))
|
||||
return NULL;
|
||||
return PyFloat_FromDouble(self->client->min_ratio);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_maxRatio(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "maxRatio");
|
||||
if (!PyArg_ParseTuple(args, ":maxRatio"))
|
||||
return NULL;
|
||||
return PyFloat_FromDouble(self->client->max_ratio);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_minSize(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
PyObject *tuple;
|
||||
|
||||
CHECK_CWRAP(self, "minSize");
|
||||
if (!PyArg_ParseTuple(args, ":minSize"))
|
||||
return NULL;
|
||||
tuple = PyTuple_New(2);
|
||||
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->client->min_size.width));
|
||||
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->client->min_size.height));
|
||||
return tuple;
|
||||
}
|
||||
|
||||
static PyObject *cwrap_maxSize(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
PyObject *tuple;
|
||||
|
||||
CHECK_CWRAP(self, "maxSize");
|
||||
if (!PyArg_ParseTuple(args, ":maxSize"))
|
||||
return NULL;
|
||||
tuple = PyTuple_New(2);
|
||||
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->client->max_size.width));
|
||||
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->client->max_size.height));
|
||||
return tuple;
|
||||
}
|
||||
|
||||
static PyObject *cwrap_sizeIncrement(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
PyObject *tuple;
|
||||
|
||||
CHECK_CWRAP(self, "sizeIncrement");
|
||||
if (!PyArg_ParseTuple(args, ":sizeIncrement"))
|
||||
return NULL;
|
||||
tuple = PyTuple_New(2);
|
||||
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->client->size_inc.width));
|
||||
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->client->size_inc.height));
|
||||
return tuple;
|
||||
}
|
||||
|
||||
static PyObject *cwrap_baseSize(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
PyObject *tuple;
|
||||
|
||||
CHECK_CWRAP(self, "baseSize");
|
||||
if (!PyArg_ParseTuple(args, ":baseSize"))
|
||||
return NULL;
|
||||
tuple = PyTuple_New(2);
|
||||
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->client->base_size.width));
|
||||
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->client->base_size.height));
|
||||
return tuple;
|
||||
}
|
||||
|
||||
static PyObject *cwrap_gravity(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "gravity");
|
||||
if (!PyArg_ParseTuple(args, ":gravity"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->gravity);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_canClose(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "canClose");
|
||||
if (!PyArg_ParseTuple(args, ":canClose"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->delete_window ? 1 : 0);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_positionRequested(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "positionRequested");
|
||||
if (!PyArg_ParseTuple(args, ":positionRequested"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->positioned ? 1 : 0);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_canFocus(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "canFocus");
|
||||
if (!PyArg_ParseTuple(args, ":canFocus"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->can_focus ||
|
||||
self->client->focus_notify);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_urgent(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "urgent");
|
||||
if (!PyArg_ParseTuple(args, ":urgent"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->urgent ? 1 : 0);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_focused(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "focused");
|
||||
if (!PyArg_ParseTuple(args, ":focused"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->focused ? 1 : 0);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_modal(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "modal");
|
||||
if (!PyArg_ParseTuple(args, ":modal"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->modal ? 1 : 0);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_shaded(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "shaded");
|
||||
if (!PyArg_ParseTuple(args, ":shaded"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->shaded ? 1 : 0);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_iconic(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "iconic");
|
||||
if (!PyArg_ParseTuple(args, ":iconc"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->iconic ? 1 : 0);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_maximizedVertical(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "maximizedVertical");
|
||||
if (!PyArg_ParseTuple(args, ":maximizedVertical"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->max_vert ? 1 : 0);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_maximizedHorizontal(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "maximizedHorizontal");
|
||||
if (!PyArg_ParseTuple(args, ":maximizedHorizontal"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->max_horz ? 1 : 0);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_skipPager(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "skipPager");
|
||||
if (!PyArg_ParseTuple(args, ":skipPager"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->skip_pager ? 1 : 0);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_skipTaskbar(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "skipTaskbar");
|
||||
if (!PyArg_ParseTuple(args, ":skipTaskbar"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->skip_taskbar ? 1 : 0);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_fullscreen(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "fullscreen");
|
||||
if (!PyArg_ParseTuple(args, ":fullscreen"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->fullscreen ? 1 : 0);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_above(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "above");
|
||||
if (!PyArg_ParseTuple(args, ":above"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->above ? 1 : 0);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_below(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "below");
|
||||
if (!PyArg_ParseTuple(args, ":below"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->below ? 1 : 0);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_layer(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "layer");
|
||||
if (!PyArg_ParseTuple(args, ":layer"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->layer);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_decorations(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "decorations");
|
||||
if (!PyArg_ParseTuple(args, ":decorations"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->decorations);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_disabledDecorations(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "disabledDecorations");
|
||||
if (!PyArg_ParseTuple(args, ":disabledDecorations"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->disabled_decorations);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_functions(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "functions");
|
||||
if (!PyArg_ParseTuple(args, ":functions"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->functions);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_visible(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "visible");
|
||||
if (!PyArg_ParseTuple(args, ":visible"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->client->frame->visible ? 1 : 0);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_decorationSize(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
PyObject *tuple;
|
||||
|
||||
CHECK_CWRAP(self, "decorationSize");
|
||||
if (!PyArg_ParseTuple(args, ":decorationSize"))
|
||||
return NULL;
|
||||
tuple = PyTuple_New(4);
|
||||
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->client->frame->size.left));
|
||||
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->client->frame->size.top));
|
||||
PyTuple_SET_ITEM(tuple, 2,
|
||||
PyInt_FromLong(self->client->frame->size.right));
|
||||
PyTuple_SET_ITEM(tuple, 3,
|
||||
PyInt_FromLong(self->client->frame->size.bottom));
|
||||
return tuple;
|
||||
}
|
||||
|
||||
static PyObject *cwrap_normal(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "normal");
|
||||
if (!PyArg_ParseTuple(args, ":normal"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(client_normal(self->client) ? 1 : 0);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_setVisible(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
int i;
|
||||
|
||||
CHECK_CWRAP(self, "setVisible");
|
||||
if (!PyArg_ParseTuple(args, "i:setVisible", &i))
|
||||
return NULL;
|
||||
if (i)
|
||||
frame_show(self->client->frame);
|
||||
else
|
||||
frame_hide(self->client->frame);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *cwrap_raiseWindow(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "raiseWindow");
|
||||
if (!PyArg_ParseTuple(args, ":raiseWindow"))
|
||||
return NULL;
|
||||
stacking_raise(self->client);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *cwrap_lowerWindow(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "lowerWindow");
|
||||
if (!PyArg_ParseTuple(args, ":lowerWindow"))
|
||||
return NULL;
|
||||
stacking_lower(self->client);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *cwrap_focus(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "focus");
|
||||
if (!PyArg_ParseTuple(args, ":focus"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(client_focus(self->client) ? 1 : 0);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_unfocus(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_CWRAP(self, "unfocus");
|
||||
if (!PyArg_ParseTuple(args, ":unfocus"))
|
||||
return NULL;
|
||||
client_unfocus(self->client);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *cwrap_move(ClientWrap *self, PyObject *args)
|
||||
{
|
||||
int x, y;
|
||||
int final = TRUE;
|
||||
CHECK_CWRAP(self, "move");
|
||||
if (!PyArg_ParseTuple(args, "ii|i:unfocus", &x, &y, &final))
|
||||
return NULL;
|
||||
/* get the client's position based on x,y for the frame */
|
||||
frame_frame_gravity(self->client->frame, &x, &y);
|
||||
|
||||
client_configure(self->client, Corner_TopLeft, x, y,
|
||||
self->client->area.width, self->client->area.height,
|
||||
TRUE, final);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
#define ATTRMETH(n, d) {#n, (PyCFunction)cwrap_##n, METH_VARARGS, #d}
|
||||
|
||||
static PyMethodDef ClientWrapMethods[] = {
|
||||
ATTRMETH(window,
|
||||
"c.window() -- Returns the window id for the Client."),
|
||||
ATTRMETH(group,
|
||||
"c.group() -- Returns the group id for the Client."),
|
||||
ATTRMETH(parent,
|
||||
"c.parent() -- Returns the parent Client for the Client, or the "
|
||||
"Client for which this Client is a transient. Returns None if it "
|
||||
"is not a transient."),
|
||||
ATTRMETH(children,
|
||||
"c.parent() -- Returns a list of child Clients for the Client, "
|
||||
"or the Clients transients."),
|
||||
ATTRMETH(desktop,
|
||||
"c.desktop() -- Returns the desktop on which the Client resides, "
|
||||
"or 0xffffffff for 'all desktops'."),
|
||||
ATTRMETH(title,
|
||||
"c.title() -- Returns the Client's title string. This is in "
|
||||
"UTF-8 encoding."),
|
||||
ATTRMETH(iconTitle,
|
||||
"c.iconTitle() -- Returns the Client's icon title string. This "
|
||||
"is in UTF-8 encoding."),
|
||||
ATTRMETH(resName,
|
||||
"c.resName() -- Returns the application's specified resource "
|
||||
"name."),
|
||||
ATTRMETH(resClass,
|
||||
"c.resClass() -- Returns the application's specified resource "
|
||||
"class."),
|
||||
ATTRMETH(role,
|
||||
"c.role() -- Returns the window's role, which should be unique "
|
||||
"for every window of an application, if it is not empty."),
|
||||
ATTRMETH(type,
|
||||
"c.type() -- Returns the window's type, one of the ob.Type_ "
|
||||
"constants. This is the logical type of the window."),
|
||||
ATTRMETH(area,
|
||||
"c.area() -- Returns the area rectangle for the Client in a "
|
||||
"tuple. The tuple's format is (x, y, width, height). This is "
|
||||
"not the area on-screen that the Client and frame occupies, but "
|
||||
"rather, the position and size that the Client has requested, "
|
||||
"before its gravity() and decorations have been applied. You "
|
||||
"should use the c.screenArea() to get the actual on-screen area "
|
||||
"for the Client."),
|
||||
ATTRMETH(screenArea,
|
||||
"c.screenArea() -- Returns the on-screen area rectangle for the "
|
||||
"Client in a tuple. The tuple's format is (x, y, width, height). "
|
||||
"This is the actual position and size of the Client plus its "
|
||||
"decorations."),
|
||||
ATTRMETH(strut,
|
||||
"c.strut() -- Returns the strut requested by the Client in a "
|
||||
"tuple. The format of the tuple is (left, top, right, bottom)."),
|
||||
ATTRMETH(logicalSize,
|
||||
"c.logicalSize() -- Returns the logical size of the Client. This "
|
||||
"is the 'user friendly' size for the Client, such as for an "
|
||||
"xterm, it will be the number of characters in the xterm "
|
||||
"instead of the number of pixels it takes up."),
|
||||
ATTRMETH(minRatio,
|
||||
"c.minRatio() -- Returns the minimum width:height ratio for "
|
||||
"the Client. A value of 0 implies no ratio enforcement."),
|
||||
ATTRMETH(maxRatio,
|
||||
"c.maxRatio() -- Returns the maximum width:height ratio for "
|
||||
"the Client. A value of 0 implies no ratio enforcement."),
|
||||
ATTRMETH(minSize,
|
||||
"c.minSize() -- Returns the minimum size of the Client."),
|
||||
ATTRMETH(maxSize,
|
||||
"c.maxSize() -- Returns the maximum size of the Client."),
|
||||
ATTRMETH(sizeIncrement,
|
||||
"c.sizeIncrement() -- Returns the size increments in which the "
|
||||
"Client must be resized."),
|
||||
ATTRMETH(baseSize,
|
||||
"c.baseSize() -- Returns the base size of the Client, which is "
|
||||
"subtracted from the Client's size before comparing to its "
|
||||
"various sizing constraints."),
|
||||
ATTRMETH(gravity,
|
||||
"c.gravity() -- Returns the gravity for the Client. One of the "
|
||||
"ob.Gravity_ constants."),
|
||||
ATTRMETH(canClose,
|
||||
"c.canClose() -- Returns whether or not the Client provides a "
|
||||
"means for Openbox to request that it close."),
|
||||
ATTRMETH(positionRequested,
|
||||
"c.positionRequested() -- Returns whether or not the Client has "
|
||||
"requested a specified position on screen. When it has it should "
|
||||
"probably not be placed using an algorithm when it is managed."),
|
||||
ATTRMETH(canFocus,
|
||||
"c.canFocus() -- Returns whether or not the Client can be "
|
||||
"given input focus."),
|
||||
ATTRMETH(urgent,
|
||||
"c.urgent() -- Returns the urgent state of the window (on/off)."),
|
||||
ATTRMETH(focused,
|
||||
"c.focused() -- Returns whether or not the Client has the input "
|
||||
"focus."),
|
||||
ATTRMETH(modal,
|
||||
"c.modal() -- Returns whether or not the Client is modal. A "
|
||||
"modal Client implies that it needs to be closed before its "
|
||||
"parent() can be used (focsed) again."),
|
||||
ATTRMETH(shaded,
|
||||
"c.shaded() -- Returns whether or not the Client is shaded. "
|
||||
"Shaded clients are hidden except for their titlebar."),
|
||||
ATTRMETH(iconic,
|
||||
"c.iconic() -- Returns whether or not the Client is iconic. "
|
||||
"Iconic windows are represented only by icons, or possibly "
|
||||
"hidden entirely."),
|
||||
ATTRMETH(maximizedVertical,
|
||||
"c.maximizedVertical() -- Returns whether or not the Client is "
|
||||
"maxized vertically. When a Client is maximized it will expand "
|
||||
"to fill as much of the screen as it can in that direction."),
|
||||
ATTRMETH(maximizedHorizontal,
|
||||
"c.maximizedHorizontal() -- Returns whether or not the Client is "
|
||||
"maxized horizontally. When a Client is maximized it will expand "
|
||||
"to fill as much of the screen as it can in that direction."),
|
||||
ATTRMETH(skipPager,
|
||||
"c.skipPager() -- Returns whether the Client as requested to be "
|
||||
"skipped by pagers."),
|
||||
ATTRMETH(skipTaskbar,
|
||||
"c.skipTaskbar() -- Returns whether the Client as requested to "
|
||||
"be skipped by taskbars."),
|
||||
ATTRMETH(fullscreen,
|
||||
"c.fullscreen() -- Returns whether the Client is in fullscreen "
|
||||
"mode."),
|
||||
ATTRMETH(above,
|
||||
"c.above() -- Returns whether the Client should be stacked above "
|
||||
"other windows of the same type."),
|
||||
ATTRMETH(below,
|
||||
"c.below() -- Returns whether the Client should be stacked below "
|
||||
"other windows of the same type."),
|
||||
ATTRMETH(layer,
|
||||
"c.layer() -- Returns the layer in which the window should be "
|
||||
"stacked. This is one of the ob.Layer_ constants. Windows in "
|
||||
"layers with higher values should be kept above windows in lower "
|
||||
"valued layers."),
|
||||
ATTRMETH(decorations,
|
||||
"c.decorations() -- Returns a mask of decorations which the "
|
||||
"Client will be given. It is made up of the ob.Decor_ constants. "
|
||||
"These can be turned off with the "
|
||||
" disabledDecorations()."),
|
||||
ATTRMETH(disabledDecorations,
|
||||
"c.disabledDecorations() -- returns a mask of decorations which "
|
||||
"are disabled on the Client. This is made up of the ob.Decor_ "
|
||||
"constants."),
|
||||
ATTRMETH(functions,
|
||||
"ob.functions() -- Returns the list of functionality for the "
|
||||
"Client, in a mask made up of the ob.Func_ constants."),
|
||||
ATTRMETH(visible,
|
||||
"ob.visible() -- Returns if the client is currently visible "
|
||||
"or hidden."),
|
||||
ATTRMETH(decorationSize,
|
||||
"c.decorationSize() -- Returns the size of the Client's "
|
||||
"decorations around the Client window, in a tuple. The format of "
|
||||
"the tuple is (left, top, right, bottom)."),
|
||||
ATTRMETH(normal,
|
||||
"c.normal() -- Returns if the window should be treated as a "
|
||||
"normal window. Some windows (desktops, docks, splash screens) "
|
||||
"should have special rules applied to them in a number of "
|
||||
"places regarding focus or user interaction."),
|
||||
ATTRMETH(setVisible,
|
||||
"c.setVisible(show) -- Shows or hides the Client."),
|
||||
ATTRMETH(raiseWindow,
|
||||
"c.raiseWindow() -- Raises the Client to the top of its layer."),
|
||||
ATTRMETH(lowerWindow,
|
||||
"c.lowerWindow() -- Lowers the Client to the bottom of its "
|
||||
"layer."),
|
||||
ATTRMETH(focus,
|
||||
"c.focus() -- Focuses the Client. Returns 1 if the Client will "
|
||||
"be focused, or 0 if it will not."),
|
||||
ATTRMETH(unfocus,
|
||||
"c.unfocus() -- Unfocuses the Client, leaving nothing focused."),
|
||||
ATTRMETH(move,
|
||||
"c.move(x, y) -- Moves the Client to the specified position. The "
|
||||
"top left corner of the Client's decorations is positioned at "
|
||||
"the given x, y."),
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Type methods/struct
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/*static PyObject *cwrap_getattr(ClientWrap *self, char *name)
|
||||
{
|
||||
CHECK_CWRAP(self, "getattr");
|
||||
return Py_FindMethod(ClientWrapAttributeMethods, (PyObject*)self, name);
|
||||
}*/
|
||||
|
||||
static void cwrap_dealloc(ClientWrap *self)
|
||||
{
|
||||
if (self->client != NULL)
|
||||
self->client->wrap = NULL;
|
||||
PyObject_Del((PyObject*) self);
|
||||
}
|
||||
|
||||
static PyObject *cwrap_repr(ClientWrap *self)
|
||||
{
|
||||
CHECK_CWRAP(self, "repr");
|
||||
return PyString_FromFormat("0x%x", (guint)self->client->window);
|
||||
}
|
||||
|
||||
static int cwrap_compare(ClientWrap *self, ClientWrap *other)
|
||||
{
|
||||
Window w1, w2;
|
||||
if (!IS_VALID_CWRAP(self)) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"This 'Client' is wrapping a client which no longer "
|
||||
"exists.");
|
||||
}
|
||||
|
||||
w1 = self->client->window;
|
||||
w2 = self->client->window;
|
||||
return w1 > w2 ? 1 : w1 < w2 ? -1 : 0;
|
||||
}
|
||||
|
||||
static PyTypeObject ClientWrapType = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0,
|
||||
"Client",
|
||||
sizeof(ClientWrap),
|
||||
0,
|
||||
(destructor) cwrap_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
(cmpfunc) cwrap_compare, /*tp_compare*/
|
||||
(reprfunc) cwrap_repr, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /*tp_hash */
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
External methods
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
void clientwrap_startup()
|
||||
{
|
||||
ClientWrapType.ob_type = &PyType_Type;
|
||||
ClientWrapType.tp_methods = ClientWrapMethods;
|
||||
PyType_Ready(&ClientWrapType);
|
||||
}
|
||||
|
||||
void clientwrap_shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
PyObject *clientwrap_new(Client *client)
|
||||
{
|
||||
g_assert(client != NULL);
|
||||
|
||||
if (client->wrap != NULL) {
|
||||
/* already has a wrapper! */
|
||||
Py_INCREF((PyObject*) client->wrap);
|
||||
} else {
|
||||
client->wrap = PyObject_New(ClientWrap, &ClientWrapType);
|
||||
client->wrap->client = client;
|
||||
}
|
||||
return (PyObject*) client->wrap;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
#ifndef __clientwrap_h
|
||||
#define __clientwrap_h
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
struct Client;
|
||||
|
||||
/* ClientWrap is a PyObject */
|
||||
typedef struct ClientWrap {
|
||||
PyObject_HEAD
|
||||
struct Client *client;
|
||||
} ClientWrap;
|
||||
|
||||
void clientwrap_startup();
|
||||
void clientwrap_shutdown();
|
||||
|
||||
PyObject *clientwrap_new(struct Client *client);
|
||||
|
||||
#endif
|
593
c/event.c
593
c/event.c
|
@ -1,593 +0,0 @@
|
|||
#include "openbox.h"
|
||||
#include "client.h"
|
||||
#include "xerror.h"
|
||||
#include "prop.h"
|
||||
#include "screen.h"
|
||||
#include "frame.h"
|
||||
#include "focus.h"
|
||||
#include "hooks.h"
|
||||
#include "stacking.h"
|
||||
#include "kbind.h"
|
||||
#include "mbind.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
static void event_process(XEvent *e);
|
||||
static void event_handle_root(XEvent *e);
|
||||
static void event_handle_client(Client *c, XEvent *e);
|
||||
|
||||
Time event_lasttime = 0;
|
||||
|
||||
/*! A list of all possible combinations of keyboard lock masks */
|
||||
static unsigned int mask_list[8];
|
||||
/*! The value of the mask for the NumLock modifier */
|
||||
static unsigned int NumLockMask;
|
||||
/*! The value of the mask for the ScrollLock modifier */
|
||||
static unsigned int ScrollLockMask;
|
||||
/*! The key codes for the modifier keys */
|
||||
static XModifierKeymap *modmap;
|
||||
/*! Table of the constant modifier masks */
|
||||
static const int mask_table[] = {
|
||||
ShiftMask, LockMask, ControlMask, Mod1Mask,
|
||||
Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
|
||||
};
|
||||
static int mask_table_size;
|
||||
|
||||
void event_startup()
|
||||
{
|
||||
mask_table_size = sizeof(mask_table) / sizeof(mask_table[0]);
|
||||
|
||||
/* get lock masks that are defined by the display (not constant) */
|
||||
modmap = XGetModifierMapping(ob_display);
|
||||
g_assert(modmap);
|
||||
if (modmap && modmap->max_keypermod > 0) {
|
||||
size_t cnt;
|
||||
const size_t size = mask_table_size * modmap->max_keypermod;
|
||||
/* get the values of the keyboard lock modifiers
|
||||
Note: Caps lock is not retrieved the same way as Scroll and Num
|
||||
lock since it doesn't need to be. */
|
||||
const KeyCode num_lock = XKeysymToKeycode(ob_display, XK_Num_Lock);
|
||||
const KeyCode scroll_lock = XKeysymToKeycode(ob_display,
|
||||
XK_Scroll_Lock);
|
||||
|
||||
for (cnt = 0; cnt < size; ++cnt) {
|
||||
if (! modmap->modifiermap[cnt]) continue;
|
||||
|
||||
if (num_lock == modmap->modifiermap[cnt])
|
||||
NumLockMask = mask_table[cnt / modmap->max_keypermod];
|
||||
if (scroll_lock == modmap->modifiermap[cnt])
|
||||
ScrollLockMask = mask_table[cnt / modmap->max_keypermod];
|
||||
}
|
||||
}
|
||||
|
||||
mask_list[0] = 0;
|
||||
mask_list[1] = LockMask;
|
||||
mask_list[2] = NumLockMask;
|
||||
mask_list[3] = LockMask | NumLockMask;
|
||||
mask_list[4] = ScrollLockMask;
|
||||
mask_list[5] = ScrollLockMask | LockMask;
|
||||
mask_list[6] = ScrollLockMask | NumLockMask;
|
||||
mask_list[7] = ScrollLockMask | LockMask | NumLockMask;
|
||||
}
|
||||
|
||||
void event_shutdown()
|
||||
{
|
||||
XFreeModifiermap(modmap);
|
||||
}
|
||||
|
||||
void event_loop()
|
||||
{
|
||||
fd_set selset;
|
||||
XEvent e;
|
||||
int x_fd;
|
||||
|
||||
while (TRUE) {
|
||||
/*
|
||||
There are slightly different event retrieval semantics here for
|
||||
local (or high bandwidth) versus remote (or low bandwidth)
|
||||
connections to the display/Xserver.
|
||||
*/
|
||||
if (ob_remote) {
|
||||
if (!XPending(ob_display))
|
||||
break;
|
||||
} else {
|
||||
/*
|
||||
This XSync allows for far more compression of events, which
|
||||
makes things like Motion events perform far far better. Since
|
||||
it also means network traffic for every event instead of every
|
||||
X events (where X is the number retrieved at a time), it
|
||||
probably should not be used for setups where Openbox is
|
||||
running on a remote/low bandwidth display/Xserver.
|
||||
*/
|
||||
XSync(ob_display, FALSE);
|
||||
if (!XEventsQueued(ob_display, QueuedAlready))
|
||||
break;
|
||||
}
|
||||
XNextEvent(ob_display, &e);
|
||||
|
||||
event_process(&e);
|
||||
}
|
||||
|
||||
x_fd = ConnectionNumber(ob_display);
|
||||
FD_ZERO(&selset);
|
||||
FD_SET(x_fd, &selset);
|
||||
select(x_fd + 1, &selset, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void event_process(XEvent *e)
|
||||
{
|
||||
XEvent ce;
|
||||
KeyCode *kp;
|
||||
Window window;
|
||||
int i, k;
|
||||
Client *client;
|
||||
GQuark context;
|
||||
static guint motion_button = 0;
|
||||
|
||||
/* pick a window */
|
||||
switch (e->type) {
|
||||
case UnmapNotify:
|
||||
window = e->xunmap.window;
|
||||
break;
|
||||
case DestroyNotify:
|
||||
window = e->xdestroywindow.window;
|
||||
break;
|
||||
case ConfigureRequest:
|
||||
window = e->xconfigurerequest.window;
|
||||
break;
|
||||
default:
|
||||
window = e->xany.window;
|
||||
}
|
||||
|
||||
/* grab the lasttime and hack up the state */
|
||||
switch (e->type) {
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
event_lasttime = e->xbutton.time;
|
||||
e->xbutton.state &= ~(LockMask | NumLockMask | ScrollLockMask);
|
||||
/* kill off the Button1Mask etc, only want the modifiers */
|
||||
e->xbutton.state &= (ControlMask | ShiftMask | Mod1Mask |
|
||||
Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
|
||||
break;
|
||||
case KeyPress:
|
||||
event_lasttime = e->xkey.time;
|
||||
e->xkey.state &= ~(LockMask | NumLockMask | ScrollLockMask);
|
||||
/* kill off the Button1Mask etc, only want the modifiers */
|
||||
e->xkey.state &= (ControlMask | ShiftMask | Mod1Mask |
|
||||
Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
|
||||
/* add to the state the mask of the modifier being pressed, if it is
|
||||
a modifier key being pressed (this is a little ugly..) */
|
||||
/* I'm commenting this out cuz i don't want "C-Control_L" being returned. */
|
||||
/* kp = modmap->modifiermap;*/
|
||||
/* for (i = 0; i < mask_table_size; ++i) {*/
|
||||
/* for (k = 0; k < modmap->max_keypermod; ++k) {*/
|
||||
/* if (*kp == e->xkey.keycode) {*/ /* found the keycode */
|
||||
/* add the mask for it */
|
||||
/* e->xkey.state |= mask_table[i];*/
|
||||
/* cause the first loop to break; */
|
||||
/* i = mask_table_size;*/
|
||||
/* break;*/ /* get outta here! */
|
||||
/* }*/
|
||||
/* ++kp;*/
|
||||
/* }*/
|
||||
/* }*/
|
||||
|
||||
break;
|
||||
case KeyRelease:
|
||||
event_lasttime = e->xkey.time;
|
||||
e->xkey.state &= ~(LockMask | NumLockMask | ScrollLockMask);
|
||||
/* kill off the Button1Mask etc, only want the modifiers */
|
||||
e->xkey.state &= (ControlMask | ShiftMask | Mod1Mask |
|
||||
Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
|
||||
/* remove from the state the mask of the modifier being released, if
|
||||
it is a modifier key being released (this is a little ugly..) */
|
||||
kp = modmap->modifiermap;
|
||||
for (i = 0; i < mask_table_size; ++i) {
|
||||
for (k = 0; k < modmap->max_keypermod; ++k) {
|
||||
if (*kp == e->xkey.keycode) { /* found the keycode */
|
||||
/* remove the mask for it */
|
||||
e->xkey.state &= ~mask_table[i];
|
||||
/* cause the first loop to break; */
|
||||
i = mask_table_size;
|
||||
break; /* get outta here! */
|
||||
}
|
||||
++kp;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MotionNotify:
|
||||
event_lasttime = e->xmotion.time;
|
||||
e->xmotion.state &= ~(LockMask | NumLockMask | ScrollLockMask);
|
||||
/* kill off the Button1Mask etc, only want the modifiers */
|
||||
e->xmotion.state &= (ControlMask | ShiftMask | Mod1Mask |
|
||||
Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
|
||||
/* compress events */
|
||||
while (XCheckTypedWindowEvent(ob_display, window, e->type, &ce)) {
|
||||
e->xmotion.x_root = ce.xmotion.x_root;
|
||||
e->xmotion.y_root = ce.xmotion.y_root;
|
||||
}
|
||||
break;
|
||||
case PropertyNotify:
|
||||
event_lasttime = e->xproperty.time;
|
||||
break;
|
||||
case FocusIn:
|
||||
case FocusOut:
|
||||
if (e->xfocus.mode == NotifyGrab)
|
||||
/*|| e.xfocus.mode == NotifyUngrab ||*/
|
||||
|
||||
/* From Metacity, from WindowMaker, ignore all funky pointer
|
||||
root events. Its commented out cuz I don't think we need this
|
||||
at all. If problems arise we can look into it */
|
||||
/*e.xfocus.detail > NotifyNonlinearVirtual) */
|
||||
return; /* skip me! */
|
||||
if (e->type == FocusOut) {
|
||||
/* FocusOut events just make us look for FocusIn events. They
|
||||
are mostly ignored otherwise. */
|
||||
XEvent fi;
|
||||
if (XCheckTypedEvent(ob_display, FocusIn, &fi)) {
|
||||
event_process(&fi);
|
||||
/* dont unfocus the window we just focused! */
|
||||
if (fi.xfocus.window == e->xfocus.window)
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
event_lasttime = e->xcrossing.time;
|
||||
if (e->xcrossing.mode != NotifyNormal)
|
||||
return; /* skip me! */
|
||||
break;
|
||||
}
|
||||
|
||||
client = g_hash_table_lookup(client_map, (gpointer)window);
|
||||
if (client) {
|
||||
event_handle_client(client, e);
|
||||
} else if (window == ob_root)
|
||||
event_handle_root(e);
|
||||
else if (e->type == ConfigureRequest) {
|
||||
/* unhandled configure requests must be used to configure the
|
||||
window directly */
|
||||
XWindowChanges xwc;
|
||||
|
||||
xwc.x = e->xconfigurerequest.x;
|
||||
xwc.y = e->xconfigurerequest.y;
|
||||
xwc.width = e->xconfigurerequest.width;
|
||||
xwc.height = e->xconfigurerequest.height;
|
||||
xwc.border_width = e->xconfigurerequest.border_width;
|
||||
xwc.sibling = e->xconfigurerequest.above;
|
||||
xwc.stack_mode = e->xconfigurerequest.detail;
|
||||
|
||||
g_message("Proxying configure event for 0x%lx\n", window);
|
||||
|
||||
/* we are not to be held responsible if someone sends us an
|
||||
invalid request! */
|
||||
xerror_set_ignore(TRUE);
|
||||
XConfigureWindow(ob_display, window,
|
||||
e->xconfigurerequest.value_mask, &xwc);
|
||||
xerror_set_ignore(FALSE);
|
||||
}
|
||||
|
||||
/* dispatch Crossing, Pointer and Key events to the hooks */
|
||||
switch(e->type) {
|
||||
case EnterNotify:
|
||||
context = frame_get_context(client, window);
|
||||
LOGICALHOOK(EnterWindow, context, client);
|
||||
break;
|
||||
case LeaveNotify:
|
||||
context = frame_get_context(client, window);
|
||||
LOGICALHOOK(LeaveWindow, context, client);
|
||||
break;
|
||||
case ButtonPress:
|
||||
if (!motion_button) motion_button = e->xbutton.button;
|
||||
context = frame_get_context(client, window);
|
||||
mbind_fire(e->xbutton.state, e->xbutton.button, context,
|
||||
Pointer_Press, client, e->xbutton.x_root,
|
||||
e->xbutton.y_root);
|
||||
break;
|
||||
case ButtonRelease:
|
||||
if (motion_button == e->xbutton.button) motion_button = 0;
|
||||
context = frame_get_context(client, window);
|
||||
mbind_fire(e->xbutton.state, e->xbutton.button, context,
|
||||
Pointer_Release, client, e->xbutton.x_root,
|
||||
e->xbutton.y_root);
|
||||
break;
|
||||
case MotionNotify:
|
||||
context = frame_get_context(client, window);
|
||||
mbind_fire(e->xkey.state, motion_button, context, Pointer_Motion,
|
||||
client, e->xmotion.x_root, e->xmotion.y_root);
|
||||
break;
|
||||
case KeyPress:
|
||||
kbind_fire(e->xkey.state, e->xkey.keycode, TRUE);
|
||||
break;
|
||||
case KeyRelease:
|
||||
kbind_fire(e->xkey.state, e->xkey.keycode, FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void event_handle_root(XEvent *e)
|
||||
{
|
||||
Atom msgtype;
|
||||
|
||||
switch(e->type) {
|
||||
case MapRequest:
|
||||
g_message("MapRequest on root");
|
||||
client_manage(e->xmap.window);
|
||||
break;
|
||||
case ClientMessage:
|
||||
if (e->xclient.format != 32) break;
|
||||
|
||||
msgtype = e->xclient.message_type;
|
||||
if (msgtype == prop_atoms.net_current_desktop) {
|
||||
unsigned int d = e->xclient.data.l[0];
|
||||
if (d <= screen_num_desktops)
|
||||
screen_set_desktop(d);
|
||||
} else if (msgtype == prop_atoms.net_number_of_desktops) {
|
||||
unsigned int d = e->xclient.data.l[0];
|
||||
if (d > 0)
|
||||
screen_set_num_desktops(d);
|
||||
} else if (msgtype == prop_atoms.net_showing_desktop) {
|
||||
screen_show_desktop(e->xclient.data.l[0] != 0);
|
||||
}
|
||||
break;
|
||||
case PropertyNotify:
|
||||
if (e->xproperty.atom == prop_atoms.net_desktop_names)
|
||||
screen_update_desktop_names();
|
||||
else if (e->xproperty.atom == prop_atoms.net_desktop_layout)
|
||||
screen_update_layout();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void event_handle_client(Client *client, XEvent *e)
|
||||
{
|
||||
XEvent ce;
|
||||
Atom msgtype;
|
||||
|
||||
switch (e->type) {
|
||||
case FocusIn:
|
||||
client->focused = TRUE;
|
||||
frame_adjust_focus(client->frame);
|
||||
|
||||
/* focus state can affect the stacking layer */
|
||||
client_calc_layer(client);
|
||||
|
||||
focus_set_client(client);
|
||||
break;
|
||||
case FocusOut:
|
||||
client->focused = FALSE;
|
||||
frame_adjust_focus(client->frame);
|
||||
|
||||
/* focus state can affect the stacking layer */
|
||||
client_calc_layer(client);
|
||||
|
||||
if (focus_client == client)
|
||||
focus_set_client(NULL);
|
||||
break;
|
||||
case ConfigureRequest:
|
||||
g_message("ConfigureRequest for window %lx", client->window);
|
||||
/* compress these */
|
||||
while (XCheckTypedWindowEvent(ob_display, client->window,
|
||||
ConfigureRequest, &ce)) {
|
||||
/* XXX if this causes bad things.. we can compress config req's
|
||||
with the same mask. */
|
||||
e->xconfigurerequest.value_mask |=
|
||||
ce.xconfigurerequest.value_mask;
|
||||
if (ce.xconfigurerequest.value_mask & CWX)
|
||||
e->xconfigurerequest.x = ce.xconfigurerequest.x;
|
||||
if (ce.xconfigurerequest.value_mask & CWY)
|
||||
e->xconfigurerequest.y = ce.xconfigurerequest.y;
|
||||
if (ce.xconfigurerequest.value_mask & CWWidth)
|
||||
e->xconfigurerequest.width = ce.xconfigurerequest.width;
|
||||
if (ce.xconfigurerequest.value_mask & CWHeight)
|
||||
e->xconfigurerequest.height = ce.xconfigurerequest.height;
|
||||
if (ce.xconfigurerequest.value_mask & CWBorderWidth)
|
||||
e->xconfigurerequest.border_width =
|
||||
ce.xconfigurerequest.border_width;
|
||||
if (ce.xconfigurerequest.value_mask & CWStackMode)
|
||||
e->xconfigurerequest.detail = ce.xconfigurerequest.detail;
|
||||
}
|
||||
|
||||
/* if we are iconic (or shaded (fvwm does this)) ignore the event */
|
||||
if (client->iconic || client->shaded) return;
|
||||
|
||||
if (e->xconfigurerequest.value_mask & CWBorderWidth)
|
||||
client->border_width = e->xconfigurerequest.border_width;
|
||||
|
||||
/* resize, then move, as specified in the EWMH section 7.7 */
|
||||
if (e->xconfigurerequest.value_mask & (CWWidth | CWHeight |
|
||||
CWX | CWY)) {
|
||||
int x, y, w, h;
|
||||
Corner corner;
|
||||
|
||||
x = (e->xconfigurerequest.value_mask & CWX) ?
|
||||
e->xconfigurerequest.x : client->area.x;
|
||||
y = (e->xconfigurerequest.value_mask & CWY) ?
|
||||
e->xconfigurerequest.y : client->area.y;
|
||||
w = (e->xconfigurerequest.value_mask & CWWidth) ?
|
||||
e->xconfigurerequest.width : client->area.width;
|
||||
h = (e->xconfigurerequest.value_mask & CWHeight) ?
|
||||
e->xconfigurerequest.height : client->area.height;
|
||||
|
||||
switch (client->gravity) {
|
||||
case NorthEastGravity:
|
||||
case EastGravity:
|
||||
corner = Corner_TopRight;
|
||||
break;
|
||||
case SouthWestGravity:
|
||||
case SouthGravity:
|
||||
corner = Corner_BottomLeft;
|
||||
break;
|
||||
case SouthEastGravity:
|
||||
corner = Corner_BottomRight;
|
||||
break;
|
||||
default: /* NorthWest, Static, etc */
|
||||
corner = Corner_TopLeft;
|
||||
}
|
||||
|
||||
client_configure(client, corner, x, y, w, h, FALSE, FALSE);
|
||||
}
|
||||
|
||||
if (e->xconfigurerequest.value_mask & CWStackMode) {
|
||||
switch (e->xconfigurerequest.detail) {
|
||||
case Below:
|
||||
case BottomIf:
|
||||
stacking_lower(client);
|
||||
break;
|
||||
|
||||
case Above:
|
||||
case TopIf:
|
||||
default:
|
||||
stacking_raise(client);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case UnmapNotify:
|
||||
if (client->ignore_unmaps) {
|
||||
client->ignore_unmaps--;
|
||||
break;
|
||||
}
|
||||
g_message("UnmapNotify for %lx", client->window);
|
||||
client_unmanage(client);
|
||||
break;
|
||||
case DestroyNotify:
|
||||
g_message("DestroyNotify for %lx", client->window);
|
||||
client_unmanage(client);
|
||||
break;
|
||||
case ReparentNotify:
|
||||
/* this is when the client is first taken captive in the frame */
|
||||
if (e->xreparent.parent == client->frame->plate) break;
|
||||
|
||||
/*
|
||||
This event is quite rare and is usually handled in unmapHandler.
|
||||
However, if the window is unmapped when the reparent event occurs,
|
||||
the window manager never sees it because an unmap event is not sent
|
||||
to an already unmapped window.
|
||||
*/
|
||||
|
||||
/* we don't want the reparent event, put it back on the stack for the
|
||||
X server to deal with after we unmanage the window */
|
||||
XPutBackEvent(ob_display, e);
|
||||
|
||||
client_unmanage(client);
|
||||
break;
|
||||
case MapRequest:
|
||||
/* we shouldn't be able to get this unless we're iconic */
|
||||
g_assert(client->iconic);
|
||||
|
||||
LOGICALHOOK(RequestActivate, g_quark_try_string("client"), client);
|
||||
break;
|
||||
case ClientMessage:
|
||||
/* validate cuz we query stuff off the client here */
|
||||
if (!client_validate(client)) break;
|
||||
|
||||
if (e->xclient.format != 32) return;
|
||||
|
||||
msgtype = e->xclient.message_type;
|
||||
if (msgtype == prop_atoms.wm_change_state) {
|
||||
/* compress changes into a single change */
|
||||
while (XCheckTypedWindowEvent(ob_display, e->type,
|
||||
client->window, &ce)) {
|
||||
/* XXX: it would be nice to compress ALL messages of a
|
||||
type, not just messages in a row without other
|
||||
message types between. */
|
||||
if (ce.xclient.message_type != msgtype) {
|
||||
XPutBackEvent(ob_display, &ce);
|
||||
break;
|
||||
}
|
||||
e->xclient = ce.xclient;
|
||||
}
|
||||
client_set_wm_state(client, e->xclient.data.l[0]);
|
||||
} else if (msgtype == prop_atoms.net_wm_desktop) {
|
||||
/* compress changes into a single change */
|
||||
while (XCheckTypedWindowEvent(ob_display, e->type,
|
||||
client->window, &ce)) {
|
||||
/* XXX: it would be nice to compress ALL messages of a
|
||||
type, not just messages in a row without other
|
||||
message types between. */
|
||||
if (ce.xclient.message_type != msgtype) {
|
||||
XPutBackEvent(ob_display, &ce);
|
||||
break;
|
||||
}
|
||||
e->xclient = ce.xclient;
|
||||
}
|
||||
client_set_desktop(client, e->xclient.data.l[0]);
|
||||
} else if (msgtype == prop_atoms.net_wm_state) {
|
||||
/* can't compress these */
|
||||
g_message("net_wm_state %s %ld %ld for 0x%lx\n",
|
||||
(e->xclient.data.l[0] == 0 ? "Remove" :
|
||||
e->xclient.data.l[0] == 1 ? "Add" :
|
||||
e->xclient.data.l[0] == 2 ? "Toggle" : "INVALID"),
|
||||
e->xclient.data.l[1], e->xclient.data.l[2],
|
||||
client->window);
|
||||
client_set_state(client, e->xclient.data.l[0],
|
||||
e->xclient.data.l[1], e->xclient.data.l[2]);
|
||||
} else if (msgtype == prop_atoms.net_close_window) {
|
||||
g_message("net_close_window for 0x%lx\n", client->window);
|
||||
client_close(client);
|
||||
} else if (msgtype == prop_atoms.net_active_window) {
|
||||
g_message("net_active_window for 0x%lx\n", client->window);
|
||||
if (screen_showing_desktop)
|
||||
screen_show_desktop(FALSE);
|
||||
if (client->iconic)
|
||||
client_iconify(client, FALSE, TRUE);
|
||||
else if (!client->frame->visible)
|
||||
/* if its not visible for other reasons, then don't mess
|
||||
with it */
|
||||
return;
|
||||
LOGICALHOOK(RequestActivate, g_quark_try_string("client"), client);
|
||||
}
|
||||
break;
|
||||
case PropertyNotify:
|
||||
/* validate cuz we query stuff off the client here */
|
||||
if (!client_validate(client)) break;
|
||||
|
||||
/* compress changes to a single property into a single change */
|
||||
while (XCheckTypedWindowEvent(ob_display, e->type,
|
||||
client->window, &ce)) {
|
||||
/* XXX: it would be nice to compress ALL changes to a property,
|
||||
not just changes in a row without other props between. */
|
||||
if (ce.xproperty.atom != e->xproperty.atom) {
|
||||
XPutBackEvent(ob_display, &ce);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
msgtype = e->xproperty.atom;
|
||||
if (msgtype == XA_WM_NORMAL_HINTS) {
|
||||
client_update_normal_hints(client);
|
||||
/* normal hints can make a window non-resizable */
|
||||
client_setup_decor_and_functions(client);
|
||||
} else if (msgtype == XA_WM_HINTS)
|
||||
client_update_wmhints(client);
|
||||
else if (msgtype == XA_WM_TRANSIENT_FOR) {
|
||||
client_update_transient_for(client);
|
||||
client_get_type(client);
|
||||
/* type may have changed, so update the layer */
|
||||
client_calc_layer(client);
|
||||
client_setup_decor_and_functions(client);
|
||||
}
|
||||
else if (msgtype == prop_atoms.net_wm_name ||
|
||||
msgtype == prop_atoms.wm_name)
|
||||
client_update_title(client);
|
||||
else if (msgtype == prop_atoms.net_wm_icon_name ||
|
||||
msgtype == prop_atoms.wm_icon_name)
|
||||
client_update_icon_title(client);
|
||||
else if (msgtype == prop_atoms.wm_class)
|
||||
client_update_class(client);
|
||||
else if (msgtype == prop_atoms.wm_protocols) {
|
||||
client_update_protocols(client);
|
||||
client_setup_decor_and_functions(client);
|
||||
}
|
||||
else if (msgtype == prop_atoms.net_wm_strut)
|
||||
client_update_strut(client);
|
||||
else if (msgtype == prop_atoms.net_wm_icon)
|
||||
client_update_icons(client);
|
||||
else if (msgtype == prop_atoms.kwm_win_icon)
|
||||
client_update_kwm_icon(client);
|
||||
}
|
||||
}
|
12
c/event.h
12
c/event.h
|
@ -1,12 +0,0 @@
|
|||
#ifndef __events_h
|
||||
#define __events_h
|
||||
|
||||
/*! Time at which the last event with a timestamp occured. */
|
||||
extern Time event_lasttime;
|
||||
|
||||
void event_startup();
|
||||
void event_shutdown();
|
||||
|
||||
void event_loop();
|
||||
|
||||
#endif
|
433
c/eventdata.c
433
c/eventdata.c
|
@ -1,433 +0,0 @@
|
|||
#include "eventdata.h"
|
||||
#include "openbox.h"
|
||||
#include "event.h"
|
||||
#include "clientwrap.h"
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
/*
|
||||
*
|
||||
* Define the type 'EventData'
|
||||
*
|
||||
*/
|
||||
|
||||
#define IS_EVENTDATA(v) ((v)->ob_type == &EventDataType)
|
||||
#define CHECK_EVENTDATA(self, funcname) { \
|
||||
if (!IS_EVENTDATA(self)) { \
|
||||
PyErr_SetString(PyExc_TypeError, \
|
||||
"descriptor '" funcname "' requires an 'EventData' " \
|
||||
"object"); \
|
||||
return NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
staticforward PyTypeObject EventDataType;
|
||||
|
||||
static PyObject *eventdata_type(EventData *self, PyObject *args)
|
||||
{
|
||||
CHECK_EVENTDATA(self, "type");
|
||||
if (!PyArg_ParseTuple(args, ":type"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(self->type);
|
||||
}
|
||||
|
||||
static PyObject *eventdata_time(EventData *self, PyObject *args)
|
||||
{
|
||||
CHECK_EVENTDATA(self, "time");
|
||||
if (!PyArg_ParseTuple(args, ":time"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(event_lasttime);
|
||||
}
|
||||
|
||||
static PyObject *eventdata_context(EventData *self, PyObject *args)
|
||||
{
|
||||
CHECK_EVENTDATA(self, "context");
|
||||
if (!PyArg_ParseTuple(args, ":context"))
|
||||
return NULL;
|
||||
return PyString_FromString(self->context);
|
||||
}
|
||||
|
||||
static PyObject *eventdata_client(EventData *self, PyObject *args)
|
||||
{
|
||||
CHECK_EVENTDATA(self, "client");
|
||||
if (!PyArg_ParseTuple(args, ":client"))
|
||||
return NULL;
|
||||
if (self->client == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
} else {
|
||||
return clientwrap_new(self->client);
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *eventdata_keycode(EventData *self, PyObject *args)
|
||||
{
|
||||
CHECK_EVENTDATA(self, "keycode");
|
||||
if (!PyArg_ParseTuple(args, ":keycode"))
|
||||
return NULL;
|
||||
switch (self->type) {
|
||||
case Key_Press:
|
||||
case Key_Release:
|
||||
break;
|
||||
default:
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"The EventData object is not a Key event");
|
||||
return NULL;
|
||||
}
|
||||
return PyInt_FromLong(self->details.key->keycode);
|
||||
}
|
||||
|
||||
static PyObject *eventdata_modifiers(EventData *self, PyObject *args)
|
||||
{
|
||||
CHECK_EVENTDATA(self, "key");
|
||||
if (!PyArg_ParseTuple(args, ":key"))
|
||||
return NULL;
|
||||
switch (self->type) {
|
||||
case Key_Press:
|
||||
case Key_Release:
|
||||
case Pointer_Press:
|
||||
case Pointer_Release:
|
||||
case Pointer_Motion:
|
||||
break;
|
||||
default:
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"The EventData object is not a Key or Pointer event");
|
||||
return NULL;
|
||||
}
|
||||
return PyInt_FromLong(self->details.key->modifiers);
|
||||
}
|
||||
|
||||
static PyObject *eventdata_keyName(EventData *self, PyObject *args)
|
||||
{
|
||||
GList *it;
|
||||
PyObject *tuple;
|
||||
int i;
|
||||
|
||||
CHECK_EVENTDATA(self, "keyName");
|
||||
if (!PyArg_ParseTuple(args, ":keyName"))
|
||||
return NULL;
|
||||
switch (self->type) {
|
||||
case Key_Press:
|
||||
case Key_Release:
|
||||
break;
|
||||
default:
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"The EventData object is not a Key event");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (self->details.key->keylist != NULL) {
|
||||
tuple = PyTuple_New(g_list_length(self->details.key->keylist));
|
||||
for (i = 0, it = self->details.key->keylist; it != NULL;
|
||||
it = it->next, ++i)
|
||||
PyTuple_SET_ITEM(tuple, i, PyString_FromString(it->data));
|
||||
return tuple;
|
||||
} else {
|
||||
GString *str = g_string_sized_new(0);
|
||||
KeySym sym;
|
||||
|
||||
if (self->details.key->modifiers & ControlMask)
|
||||
g_string_append(str, "C-");
|
||||
if (self->details.key->modifiers & ShiftMask)
|
||||
g_string_append(str, "S-");
|
||||
if (self->details.key->modifiers & Mod1Mask)
|
||||
g_string_append(str, "Mod1-");
|
||||
if (self->details.key->modifiers & Mod2Mask)
|
||||
g_string_append(str, "Mod2-");
|
||||
if (self->details.key->modifiers & Mod3Mask)
|
||||
g_string_append(str, "Mod3-");
|
||||
if (self->details.key->modifiers & Mod4Mask)
|
||||
g_string_append(str, "Mod4-");
|
||||
if (self->details.key->modifiers & Mod5Mask)
|
||||
g_string_append(str, "Mod5-");
|
||||
|
||||
sym = XKeycodeToKeysym(ob_display, self->details.key->keycode, 0);
|
||||
if (sym == NoSymbol)
|
||||
g_string_append(str, "NoSymbol");
|
||||
else {
|
||||
char *name = XKeysymToString(sym);
|
||||
if (name == NULL)
|
||||
name = "Undefined";
|
||||
g_string_append(str, name);
|
||||
}
|
||||
|
||||
tuple = PyTuple_New(1);
|
||||
PyTuple_SET_ITEM(tuple, 0, PyString_FromString(str->str));
|
||||
g_string_free(str, TRUE);
|
||||
|
||||
return tuple;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *eventdata_button(EventData *self, PyObject *args)
|
||||
{
|
||||
CHECK_EVENTDATA(self, "button");
|
||||
if (!PyArg_ParseTuple(args, ":button"))
|
||||
return NULL;
|
||||
switch (self->type) {
|
||||
case Pointer_Press:
|
||||
case Pointer_Release:
|
||||
case Pointer_Motion:
|
||||
break;
|
||||
default:
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"The EventData object is not a Pointer event");
|
||||
return NULL;
|
||||
}
|
||||
return PyInt_FromLong(self->details.pointer->button);
|
||||
}
|
||||
|
||||
static PyObject *eventdata_buttonName(EventData *self, PyObject *args)
|
||||
{
|
||||
CHECK_EVENTDATA(self, "buttonName");
|
||||
if (!PyArg_ParseTuple(args, ":buttonName"))
|
||||
return NULL;
|
||||
switch (self->type) {
|
||||
case Pointer_Press:
|
||||
case Pointer_Release:
|
||||
case Pointer_Motion:
|
||||
break;
|
||||
default:
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"The EventData object is not a Pointer event");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (self->details.pointer->name != NULL) {
|
||||
return PyString_FromString(self->details.pointer->name);
|
||||
} else {
|
||||
PyObject *pystr;
|
||||
GString *str = g_string_sized_new(0);
|
||||
|
||||
if (self->details.pointer->modifiers & ControlMask)
|
||||
g_string_append(str, "C-");
|
||||
if (self->details.pointer->modifiers & ShiftMask)
|
||||
g_string_append(str, "S-");
|
||||
if (self->details.pointer->modifiers & Mod1Mask)
|
||||
g_string_append(str, "Mod1-");
|
||||
if (self->details.pointer->modifiers & Mod2Mask)
|
||||
g_string_append(str, "Mod2-");
|
||||
if (self->details.pointer->modifiers & Mod3Mask)
|
||||
g_string_append(str, "Mod3-");
|
||||
if (self->details.pointer->modifiers & Mod4Mask)
|
||||
g_string_append(str, "Mod4-");
|
||||
if (self->details.pointer->modifiers & Mod5Mask)
|
||||
g_string_append(str, "Mod5-");
|
||||
|
||||
g_string_append_printf(str, "%d", self->details.pointer->button);
|
||||
|
||||
pystr = PyString_FromString(str->str);
|
||||
|
||||
g_string_free(str, TRUE);
|
||||
|
||||
return pystr;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *eventdata_position(EventData *self, PyObject *args)
|
||||
{
|
||||
PyObject *tuple;
|
||||
|
||||
CHECK_EVENTDATA(self, "position");
|
||||
if (!PyArg_ParseTuple(args, ":position"))
|
||||
return NULL;
|
||||
switch (self->type) {
|
||||
case Pointer_Press:
|
||||
case Pointer_Release:
|
||||
case Pointer_Motion:
|
||||
break;
|
||||
default:
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"The EventData object is not a Pointer event");
|
||||
return NULL;
|
||||
}
|
||||
tuple = PyTuple_New(2);
|
||||
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->details.pointer->xroot));
|
||||
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->details.pointer->yroot));
|
||||
return tuple;
|
||||
}
|
||||
|
||||
static PyMethodDef EventDataAttributeMethods[] = {
|
||||
{"type", (PyCFunction)eventdata_type, METH_VARARGS,
|
||||
"data.type() -- Return the event type"},
|
||||
{"context", (PyCFunction)eventdata_context, METH_VARARGS,
|
||||
"data.context() -- Return the context for the event. If it is "
|
||||
"\"client\", then data.client() can be used to find out the "
|
||||
"client."},
|
||||
{"client", (PyCFunction)eventdata_client, METH_VARARGS,
|
||||
"data.client() -- Return the client for the event. This may be None if "
|
||||
"there is no client, even if data.context() gives Context_Client."},
|
||||
{"time", (PyCFunction)eventdata_time, METH_VARARGS,
|
||||
"data.time() -- Return the time at which the last X event occured with "
|
||||
"a timestamp. Should be the time at which this event, or the event that "
|
||||
"caused this event to occur happened."},
|
||||
{"modifiers", (PyCFunction)eventdata_modifiers, METH_VARARGS,
|
||||
"data.modifiers() -- Return the modifier keymask that was pressed "
|
||||
"when the event occured. A bitmask of ShiftMask, LockMask, ControlMask, "
|
||||
"Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask. Cannot be used "
|
||||
"when the data.type() is not a Key_* or Pointer_* event type."},
|
||||
{"keycode", (PyCFunction)eventdata_keycode, METH_VARARGS,
|
||||
"data.keycode() -- Return the keycode for the key which generated the "
|
||||
"event. Cannot be used when the data.type() is not a Key_* event type."},
|
||||
{"keyName", (PyCFunction)eventdata_keyName, METH_VARARGS,
|
||||
"data.keyName() -- Return a tuple of the string names of the key which "
|
||||
"generated the event. Cannot be used when the data.type() is not a Key_* "
|
||||
"event "
|
||||
"type."},
|
||||
{"button", (PyCFunction)eventdata_button, METH_VARARGS,
|
||||
"data.button() -- Return the pointer button which generated the event. "
|
||||
"Cannot be used when the data.type() is not a Pointer_* event type."},
|
||||
{"buttonName", (PyCFunction)eventdata_keyName, METH_VARARGS,
|
||||
"data.buttonName() -- Return the name of the button which generated the "
|
||||
"event. Cannot be used when the data.type() is not a Pointer_* event "
|
||||
"type."},
|
||||
{"position", (PyCFunction)eventdata_position, METH_VARARGS,
|
||||
"data.position() -- Returns the current position of the pointer on the "
|
||||
"root window when the event was generated. Gives the position in a tuple "
|
||||
"with a format of (x, y). Cannot be used when the data.type() is not a "
|
||||
"Pointer_* event type."},
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
static void data_dealloc(EventData *self)
|
||||
{
|
||||
GList *it;
|
||||
|
||||
switch(self->type) {
|
||||
case Logical_EnterWindow:
|
||||
case Logical_LeaveWindow:
|
||||
case Logical_NewWindow:
|
||||
case Logical_CloseWindow:
|
||||
case Logical_Startup:
|
||||
case Logical_Shutdown:
|
||||
case Logical_RequestActivate:
|
||||
case Logical_WindowShow:
|
||||
case Logical_WindowHide:
|
||||
case Logical_Focus:
|
||||
case Logical_Bell:
|
||||
case Logical_UrgentWindow:
|
||||
g_free(self->details.logical);
|
||||
break;
|
||||
case Pointer_Press:
|
||||
case Pointer_Release:
|
||||
case Pointer_Motion:
|
||||
if (self->details.pointer->name != NULL)
|
||||
g_free(self->details.pointer->name);
|
||||
g_free(self->details.pointer);
|
||||
break;
|
||||
case Key_Press:
|
||||
case Key_Release:
|
||||
for (it = self->details.key->keylist; it != NULL; it = it->next)
|
||||
g_free(it->data);
|
||||
g_list_free(self->details.key->keylist);
|
||||
g_free(self->details.key);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
PyObject_Del((PyObject*) self);
|
||||
}
|
||||
|
||||
static PyObject *eventdata_getattr(EventData *self, char *name)
|
||||
{
|
||||
return Py_FindMethod(EventDataAttributeMethods, (PyObject*)self, name);
|
||||
}
|
||||
|
||||
static PyTypeObject EventDataType = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0,
|
||||
"EventData",
|
||||
sizeof(EventData),
|
||||
0,
|
||||
(destructor) data_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
(getattrfunc) eventdata_getattr, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /*tp_hash */
|
||||
};
|
||||
|
||||
|
||||
|
||||
void eventdata_startup()
|
||||
{
|
||||
EventDataType.ob_type = &PyType_Type;
|
||||
PyType_Ready(&EventDataType);
|
||||
}
|
||||
|
||||
void eventdata_shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
void eventdata_free(EventData *data)
|
||||
{
|
||||
Py_DECREF(data);
|
||||
}
|
||||
|
||||
EventData *eventdata_new_logical(EventType type, GQuark context,
|
||||
struct Client *client)
|
||||
{
|
||||
EventData *data;
|
||||
|
||||
g_assert(type < Pointer_Press);
|
||||
|
||||
data = PyObject_New(EventData, &EventDataType);
|
||||
data->type = type;
|
||||
data->context = g_quark_to_string(context);
|
||||
data->client = client;
|
||||
data->details.logical = g_new(LogicalEvent, 1);
|
||||
return data;
|
||||
}
|
||||
|
||||
EventData *eventdata_new_pointer(EventType type, GQuark context,
|
||||
struct Client *client, guint modifiers,
|
||||
guint button, char *name,
|
||||
int xroot, int yroot)
|
||||
{
|
||||
EventData *data;
|
||||
|
||||
g_assert(type >= Pointer_Press && type < Key_Press);
|
||||
|
||||
data = PyObject_New(EventData, &EventDataType);
|
||||
data->type = type;
|
||||
data->context = g_quark_to_string(context);
|
||||
data->client = client;
|
||||
data->details.pointer = g_new(PointerEvent, 1);
|
||||
data->details.pointer->modifiers = modifiers;
|
||||
data->details.pointer->button = button;
|
||||
data->details.pointer->name = name == NULL ? name : g_strdup(name);
|
||||
data->details.pointer->xroot = xroot;
|
||||
data->details.pointer->yroot = yroot;
|
||||
return data;
|
||||
}
|
||||
|
||||
EventData *eventdata_new_key(EventType type, GQuark context,
|
||||
struct Client *client, guint modifiers,
|
||||
guint keycode, GList *keylist)
|
||||
{
|
||||
EventData *data;
|
||||
GList *mykeylist, *it;
|
||||
|
||||
g_assert(type >= Key_Press);
|
||||
|
||||
data = PyObject_New(EventData, &EventDataType);
|
||||
data->type = type;
|
||||
data->context = g_quark_to_string(context);
|
||||
data->client = client;
|
||||
data->details.key = g_new(KeyEvent, 1);
|
||||
|
||||
/* make a copy of the keylist.
|
||||
If the user were to clear the key bindings, then the keylist given here
|
||||
would no longer point at valid memory.*/
|
||||
mykeylist = g_list_copy(keylist); /* shallow copy */
|
||||
for (it = mykeylist; it != NULL; it = it->next) /* deep copy */
|
||||
it->data = g_strdup(it->data);
|
||||
|
||||
data->details.key->keylist = mykeylist;
|
||||
data->details.key->keycode = keycode;
|
||||
data->details.key->modifiers = modifiers;
|
||||
return data;
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
#ifndef __eventdata_h
|
||||
#define __eventdata_h
|
||||
|
||||
#include "obexport.h"
|
||||
#include <Python.h>
|
||||
#include <glib.h>
|
||||
|
||||
struct Client;
|
||||
|
||||
typedef struct {
|
||||
int temp:1; /* just a placeholder to kill warnings for now.. */
|
||||
} LogicalEvent;
|
||||
|
||||
typedef struct {
|
||||
/*! The button which generated the event */
|
||||
guint button;
|
||||
/*! The pointer's x position on the root window when the event occured */
|
||||
int xroot;
|
||||
/*! The pointer's y position on the root window when the event occured */
|
||||
int yroot;
|
||||
/*! The modifiers that were pressed when the event occured. A bitmask of:
|
||||
ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask,
|
||||
Mod4Mask, Mod5Mask */
|
||||
guint modifiers;
|
||||
/*! The name of the button/modifier combination being pressed,
|
||||
eg "Mod1-1" */
|
||||
char *name;
|
||||
} PointerEvent;
|
||||
|
||||
typedef struct {
|
||||
/*! The keycode of the key which generated the event */
|
||||
guint keycode;
|
||||
/*! The modifiers that were pressed when the event occured. A bitmask of:
|
||||
ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask,
|
||||
Mod4Mask, Mod5Mask */
|
||||
guint modifiers;
|
||||
/* The list of strings which make up the chain that fired,
|
||||
eg ("Mod1-a", "a") */
|
||||
GList *keylist;
|
||||
} KeyEvent;
|
||||
|
||||
/* EventData is a PyObject */
|
||||
typedef struct EventData {
|
||||
PyObject_HEAD
|
||||
/* The type of event which occured */
|
||||
EventType type;
|
||||
/*! The context in which the event occured, the type of window it occured
|
||||
for. */
|
||||
const char *context;
|
||||
/* The Client on which the event occured, or NULL */
|
||||
struct Client *client;
|
||||
|
||||
union EventDetails {
|
||||
LogicalEvent *logical;
|
||||
PointerEvent *pointer;
|
||||
KeyEvent *key;
|
||||
} details;
|
||||
} EventData;
|
||||
|
||||
void eventdata_startup();
|
||||
void eventdata_shutdown();
|
||||
|
||||
EventData *eventdata_new_logical(EventType type, GQuark context,
|
||||
struct Client *client);
|
||||
EventData *eventdata_new_pointer(EventType type, GQuark context,
|
||||
struct Client *client, guint modifiers,
|
||||
guint button, char *name,
|
||||
int xroot, int yroot);
|
||||
EventData *eventdata_new_key(EventType type, GQuark context,
|
||||
struct Client *client, guint modifiers,
|
||||
guint keycode, GList *keylist);
|
||||
void eventdata_free(EventData *data);
|
||||
|
||||
#endif
|
|
@ -1,34 +0,0 @@
|
|||
#include "openbox.h"
|
||||
#include "extensions.h"
|
||||
|
||||
gboolean extensions_xkb = FALSE;
|
||||
int extensions_xkb_event_basep;
|
||||
gboolean extensions_shape = FALSE;
|
||||
int extensions_shape_event_basep;
|
||||
gboolean extensions_xinerama = FALSE;
|
||||
int extensions_xinerama_event_basep;
|
||||
|
||||
|
||||
void extensions_query_all()
|
||||
{
|
||||
int junk;
|
||||
(void)junk;
|
||||
|
||||
#ifdef XKB
|
||||
extensions_xkb =
|
||||
XkbQueryExtension(ob_display, &junk, &extensions_xkb_event_basep,
|
||||
&junk, NULL, NULL);
|
||||
#endif
|
||||
|
||||
#ifdef SHAPE
|
||||
extensions_shape =
|
||||
XShapeQueryExtension(ob_display, &extensions_shape_event_basep,
|
||||
&junk);
|
||||
#endif
|
||||
|
||||
#ifdef XINERAMA
|
||||
extensions_xinerama =
|
||||
XineramaQueryExtension(ob_display, &extensions_xinerama_event_basep,
|
||||
&junk);
|
||||
#endif
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
#ifndef __extensions_h
|
||||
#define __extensions_h
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#ifdef XKB
|
||||
#include <X11/XKBlib.h>
|
||||
#endif
|
||||
#ifdef SHAPE
|
||||
#include <X11/extensions/shape.h>
|
||||
#endif
|
||||
#ifdef XINERAMA
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
#endif
|
||||
#include <glib.h>
|
||||
|
||||
/*! Does the display have the XKB extension? */
|
||||
extern gboolean extensions_xkb;
|
||||
/*! Base for events for the XKB extension */
|
||||
extern int extensions_xkb_event_basep;
|
||||
|
||||
/*! Does the display have the Shape extension? */
|
||||
extern gboolean extensions_shape;
|
||||
/*! Base for events for the Shape extension */
|
||||
extern int extensions_shape_event_basep;
|
||||
|
||||
/*! Does the display have the Xinerama extension? */
|
||||
extern gboolean extensions_xinerama;
|
||||
/*! Base for events for the Xinerama extension */
|
||||
extern int extensions_xinerama_event_basep;
|
||||
|
||||
void extensions_query_all();
|
||||
|
||||
#endif
|
56
c/focus.c
56
c/focus.c
|
@ -1,56 +0,0 @@
|
|||
#include "openbox.h"
|
||||
#include "client.h"
|
||||
#include "screen.h"
|
||||
#include "prop.h"
|
||||
#include "hooks.h"
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
Client *focus_client = NULL;
|
||||
|
||||
Window focus_backup = None;
|
||||
|
||||
void focus_set_client(Client *client);
|
||||
|
||||
void focus_startup()
|
||||
{
|
||||
/* create the window which gets focus when no clients get it. Have to
|
||||
make it override-redirect so we don't try manage it, since it is
|
||||
mapped. */
|
||||
XSetWindowAttributes attrib;
|
||||
|
||||
attrib.override_redirect = TRUE;
|
||||
focus_backup = XCreateWindow(ob_display, ob_root,
|
||||
-100, -100, 1, 1, 0, 0, InputOnly,
|
||||
CopyFromParent, CWOverrideRedirect, &attrib);
|
||||
XMapRaised(ob_display, focus_backup);
|
||||
|
||||
/* start with nothing focused */
|
||||
focus_set_client(NULL);
|
||||
}
|
||||
|
||||
void focus_set_client(Client *client)
|
||||
{
|
||||
Window active;
|
||||
|
||||
/* sometimes this is called with the already-focused window, this is
|
||||
important for the python scripts to work (eg, c = 0 twice). don't just
|
||||
return if _focused_client == c */
|
||||
|
||||
/* uninstall the old colormap, and install the new one */
|
||||
screen_install_colormap(focus_client, FALSE);
|
||||
screen_install_colormap(client, TRUE);
|
||||
|
||||
|
||||
if (client == NULL) {
|
||||
/* when nothing will be focused, send focus to the backup target */
|
||||
XSetInputFocus(ob_display, focus_backup, RevertToNone, CurrentTime);
|
||||
}
|
||||
|
||||
focus_client = client;
|
||||
|
||||
/* set the NET_ACTIVE_WINDOW hint */
|
||||
active = client ? client->window : None;
|
||||
PROP_SET32(ob_root, net_active_window, window, active);
|
||||
|
||||
LOGICALHOOK(Focus, g_quark_try_string("client"), client);
|
||||
}
|
20
c/focus.h
20
c/focus.h
|
@ -1,20 +0,0 @@
|
|||
#ifndef __focus_h
|
||||
#define __focus_h
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
struct Client;
|
||||
|
||||
/*! The window which gets focus when nothing else will be focused */
|
||||
extern Window focus_backup;
|
||||
|
||||
/*! The client which is currently focused */
|
||||
extern struct Client *focus_client;
|
||||
|
||||
void focus_startup();
|
||||
|
||||
/*! Specify which client is currently focused, this doesn't actually
|
||||
send focus anywhere, its called by the Focus event handlers */
|
||||
void focus_set_client(struct Client *client);
|
||||
|
||||
#endif
|
533
c/frame.c
533
c/frame.c
|
@ -1,533 +0,0 @@
|
|||
#include "openbox.h"
|
||||
#include "frame.h"
|
||||
#include "extensions.h"
|
||||
#include "hooks.h"
|
||||
|
||||
#define PLATE_EVENTMASK (SubstructureRedirectMask | ButtonPressMask)
|
||||
#define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask)
|
||||
|
||||
static Window createWindow(Window parent, unsigned long mask,
|
||||
XSetWindowAttributes *attrib)
|
||||
{
|
||||
/* XXX DONT USE THE DEFAULT SHIT */
|
||||
return XCreateWindow(ob_display, parent, 0, 0, 1, 1, 0,
|
||||
DefaultDepth(ob_display, ob_screen), InputOutput,
|
||||
DefaultVisual(ob_display, ob_screen),
|
||||
mask, attrib);
|
||||
|
||||
}
|
||||
|
||||
Frame *frame_new(Client *client)
|
||||
{
|
||||
XSetWindowAttributes attrib;
|
||||
unsigned long mask;
|
||||
Frame *self;
|
||||
|
||||
self = g_new(Frame, 1);
|
||||
|
||||
self->client = client;
|
||||
self->visible = FALSE;
|
||||
|
||||
/* create all of the decor windows */
|
||||
mask = CWOverrideRedirect | CWEventMask;
|
||||
attrib.event_mask = FRAME_EVENTMASK;
|
||||
attrib.override_redirect = TRUE;
|
||||
self->window = createWindow(ob_root, mask, &attrib);
|
||||
|
||||
mask = 0;
|
||||
self->plate = createWindow(self->window, mask, &attrib);
|
||||
mask = CWEventMask;
|
||||
attrib.event_mask = (ButtonPressMask | ButtonReleaseMask |
|
||||
ButtonMotionMask | ExposureMask);
|
||||
self->title = createWindow(self->window, mask, &attrib);
|
||||
self->label = createWindow(self->title, mask, &attrib);
|
||||
self->max = createWindow(self->title, mask, &attrib);
|
||||
self->close = createWindow(self->title, mask, &attrib);
|
||||
self->desk = createWindow(self->title, mask, &attrib);
|
||||
self->icon = createWindow(self->title, mask, &attrib);
|
||||
self->iconify = createWindow(self->title, mask, &attrib);
|
||||
self->handle = createWindow(self->window, mask, &attrib);
|
||||
mask |= CWCursor;
|
||||
attrib.cursor = ob_cursors.ll_angle;
|
||||
self->lgrip = createWindow(self->handle, mask, &attrib);
|
||||
attrib.cursor = ob_cursors.lr_angle;
|
||||
self->rgrip = createWindow(self->handle, mask, &attrib);
|
||||
|
||||
/* the other stuff is shown based on decor settings */
|
||||
XMapWindow(ob_display, self->plate);
|
||||
XMapWindow(ob_display, self->lgrip);
|
||||
XMapWindow(ob_display, self->rgrip);
|
||||
XMapWindow(ob_display, self->label);
|
||||
|
||||
|
||||
/* XXX TEMPORARY OF COURSE!@&*(@! */
|
||||
|
||||
XSetWindowBackground(ob_display, self->title, 0x3333aa);
|
||||
XSetWindowBackground(ob_display, self->handle, 0x3333aa);
|
||||
XSetWindowBackground(ob_display, self->lgrip, 0x2233aa);
|
||||
XSetWindowBackground(ob_display, self->rgrip, 0x2233aa);
|
||||
|
||||
XSetWindowBorder(ob_display, self->window, 0);
|
||||
XSetWindowBorder(ob_display, self->label, 0);
|
||||
XSetWindowBorder(ob_display, self->rgrip, 0);
|
||||
XSetWindowBorder(ob_display, self->lgrip, 0);
|
||||
XSetWindowBorder(ob_display, self->plate, 0x771122);
|
||||
|
||||
/* XXX /TEMPORARY OF COURSE!@&*(@! */
|
||||
|
||||
/* set all the windows for the frame in the client_map */
|
||||
g_hash_table_insert(client_map, (gpointer)self->window, self->client);
|
||||
g_hash_table_insert(client_map, (gpointer)self->plate, self->client);
|
||||
g_hash_table_insert(client_map, (gpointer)self->title, self->client);
|
||||
g_hash_table_insert(client_map, (gpointer)self->label, self->client);
|
||||
g_hash_table_insert(client_map, (gpointer)self->max, self->client);
|
||||
g_hash_table_insert(client_map, (gpointer)self->close, self->client);
|
||||
g_hash_table_insert(client_map, (gpointer)self->desk, self->client);
|
||||
g_hash_table_insert(client_map, (gpointer)self->icon, self->client);
|
||||
g_hash_table_insert(client_map, (gpointer)self->iconify, self->client);
|
||||
g_hash_table_insert(client_map, (gpointer)self->handle, self->client);
|
||||
g_hash_table_insert(client_map, (gpointer)self->lgrip, self->client);
|
||||
g_hash_table_insert(client_map, (gpointer)self->rgrip, self->client);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void frame_free(Frame *self)
|
||||
{
|
||||
/* remove all the windows for the frame from the client_map */
|
||||
g_hash_table_remove(client_map, (gpointer)self->window);
|
||||
g_hash_table_remove(client_map, (gpointer)self->plate);
|
||||
g_hash_table_remove(client_map, (gpointer)self->title);
|
||||
g_hash_table_remove(client_map, (gpointer)self->label);
|
||||
g_hash_table_remove(client_map, (gpointer)self->max);
|
||||
g_hash_table_remove(client_map, (gpointer)self->close);
|
||||
g_hash_table_remove(client_map, (gpointer)self->desk);
|
||||
g_hash_table_remove(client_map, (gpointer)self->icon);
|
||||
g_hash_table_remove(client_map, (gpointer)self->iconify);
|
||||
g_hash_table_remove(client_map, (gpointer)self->handle);
|
||||
g_hash_table_remove(client_map, (gpointer)self->lgrip);
|
||||
g_hash_table_remove(client_map, (gpointer)self->rgrip);
|
||||
|
||||
XDestroyWindow(ob_display, self->window);
|
||||
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
void frame_grab_client(Frame *self)
|
||||
{
|
||||
/* reparent the client to the frame */
|
||||
XReparentWindow(ob_display, self->client->window, self->plate, 0, 0);
|
||||
/*
|
||||
When reparenting the client window, it is usually not mapped yet, since
|
||||
this occurs from a MapRequest. However, in the case where Openbox is
|
||||
starting up, the window is already mapped, so we'll see unmap events for
|
||||
it. There are 2 unmap events generated that we see, one with the 'event'
|
||||
member set the root window, and one set to the client, but both get
|
||||
handled and need to be ignored.
|
||||
*/
|
||||
if (ob_state == State_Starting)
|
||||
self->client->ignore_unmaps += 2;
|
||||
|
||||
/* select the event mask on the client's parent (to receive config/map
|
||||
req's) the ButtonPress is to catch clicks on the client border */
|
||||
XSelectInput(ob_display, self->plate, PLATE_EVENTMASK);
|
||||
|
||||
/* map the client so it maps when the frame does */
|
||||
XMapWindow(ob_display, self->client->window);
|
||||
|
||||
frame_adjust_size(self);
|
||||
frame_adjust_position(self);
|
||||
}
|
||||
|
||||
void frame_release_client(Frame *self)
|
||||
{
|
||||
XEvent ev;
|
||||
|
||||
/* check if the app has already reparented its window away */
|
||||
if (XCheckTypedWindowEvent(ob_display, self->client->window,
|
||||
ReparentNotify, &ev)) {
|
||||
XPutBackEvent(ob_display, &ev);
|
||||
/* re-map the window since the unmanaging process unmaps it */
|
||||
XMapWindow(ob_display, self->client->window);
|
||||
} else {
|
||||
/* according to the ICCCM - if the client doesn't reparent itself,
|
||||
then we will reparent the window to root for them */
|
||||
XReparentWindow(ob_display, self->client->window, ob_root,
|
||||
self->client->area.x, self->client->area.y);
|
||||
}
|
||||
}
|
||||
|
||||
void frame_show(Frame *self)
|
||||
{
|
||||
if (!self->visible) {
|
||||
self->visible = TRUE;
|
||||
XMapWindow(ob_display, self->window);
|
||||
LOGICALHOOK(WindowShow, g_quark_try_string("client"), self->client);
|
||||
}
|
||||
}
|
||||
|
||||
void frame_hide(Frame *self)
|
||||
{
|
||||
if (self->visible) {
|
||||
self->visible = FALSE;
|
||||
self->client->ignore_unmaps++;
|
||||
XUnmapWindow(ob_display, self->window);
|
||||
LOGICALHOOK(WindowHide, g_quark_try_string("client"), self->client);
|
||||
}
|
||||
}
|
||||
|
||||
void frame_adjust_size(Frame *self)
|
||||
{
|
||||
self->decorations = self->client->decorations;
|
||||
|
||||
/* XXX set shit from the style */
|
||||
self->geom.font_height = 10;
|
||||
self->geom.bevel = 1;
|
||||
self->geom.button_size = self->geom.font_height - 2;
|
||||
self->geom.handle_height = 2;
|
||||
self->geom.grip_width = self->geom.button_size * 2;
|
||||
XResizeWindow(ob_display, self->lgrip, self->geom.grip_width,
|
||||
self->geom.handle_height);
|
||||
XResizeWindow(ob_display, self->rgrip, self->geom.grip_width,
|
||||
self->geom.handle_height);
|
||||
|
||||
|
||||
|
||||
|
||||
if (self->decorations & Decor_Border) {
|
||||
self->geom.bwidth = 1;/*XXX style->frameBorderWidth(); */
|
||||
self->geom.cbwidth = 1; /*XXX style->clientBorderWidth(); */
|
||||
} else {
|
||||
self->geom.bwidth = self->geom.cbwidth = 0;
|
||||
}
|
||||
STRUT_SET(self->innersize, self->geom.cbwidth, self->geom.cbwidth,
|
||||
self->geom.cbwidth, self->geom.cbwidth);
|
||||
self->geom.width = self->client->area.width + self->geom.cbwidth * 2;
|
||||
g_assert(self->geom.width > 0);
|
||||
|
||||
/* set border widths */
|
||||
XSetWindowBorderWidth(ob_display, self->plate, self->geom.cbwidth);
|
||||
XSetWindowBorderWidth(ob_display, self->window, self->geom.bwidth);
|
||||
XSetWindowBorderWidth(ob_display, self->title, self->geom.bwidth);
|
||||
XSetWindowBorderWidth(ob_display, self->handle, self->geom.bwidth);
|
||||
XSetWindowBorderWidth(ob_display, self->lgrip, self->geom.bwidth);
|
||||
XSetWindowBorderWidth(ob_display, self->rgrip, self->geom.bwidth);
|
||||
|
||||
/* position/size and map/unmap all the windows */
|
||||
|
||||
if (self->decorations & Decor_Titlebar) {
|
||||
self->geom.title_height = self->geom.font_height +
|
||||
self->geom.bevel * 2;
|
||||
XMoveResizeWindow(ob_display, self->title,
|
||||
-self->geom.bwidth, -self->geom.bwidth,
|
||||
self->geom.width, self->geom.title_height);
|
||||
self->innersize.top += self->geom.title_height + self->geom.bwidth;
|
||||
XMapWindow(ob_display, self->title);
|
||||
|
||||
/* layout the title bar elements */
|
||||
/*XXX layoutTitle(); */
|
||||
} else {
|
||||
XUnmapWindow(ob_display, self->title);
|
||||
/* make all the titlebar stuff not render */
|
||||
self->decorations &= ~(Decor_Icon | Decor_Iconify |
|
||||
Decor_Maximize | Decor_Close |
|
||||
Decor_AllDesktops);
|
||||
}
|
||||
|
||||
if (self->decorations & Decor_Handle) {
|
||||
self->geom.handle_y = self->innersize.top +
|
||||
self->client->area.height + self->geom.cbwidth;
|
||||
XMoveResizeWindow(ob_display, self->handle,
|
||||
-self->geom.bwidth, self->geom.handle_y,
|
||||
self->geom.width, self->geom.handle_height);
|
||||
XMoveWindow(ob_display, self->lgrip,
|
||||
-self->geom.bwidth, -self->geom.bwidth);
|
||||
XMoveWindow(ob_display, self->rgrip,
|
||||
-self->geom.bwidth + self->geom.width -
|
||||
self->geom.grip_width, -self->geom.bwidth);
|
||||
self->innersize.bottom += self->geom.handle_height +
|
||||
self->geom.bwidth;
|
||||
XMapWindow(ob_display, self->handle);
|
||||
} else
|
||||
XUnmapWindow(ob_display, self->handle);
|
||||
|
||||
XResizeWindow(ob_display, self->window, self->geom.width,
|
||||
(self->client->shaded ? self->geom.title_height :
|
||||
self->innersize.top + self->innersize.bottom +
|
||||
self->client->area.height));
|
||||
|
||||
/* do this in two steps because clients whose gravity is set to
|
||||
'Static' don't end up getting moved at all with an XMoveResizeWindow */
|
||||
XMoveWindow(ob_display, self->plate,
|
||||
self->innersize.left - self->geom.cbwidth,
|
||||
self->innersize.top - self->geom.cbwidth);
|
||||
XResizeWindow(ob_display, self->plate, self->client->area.width,
|
||||
self->client->area.height);
|
||||
|
||||
STRUT_SET(self->size,
|
||||
self->innersize.left + self->geom.bwidth,
|
||||
self->innersize.right + self->geom.bwidth,
|
||||
self->innersize.top + self->geom.bwidth,
|
||||
self->innersize.bottom + self->geom.bwidth);
|
||||
|
||||
RECT_SET_SIZE(self->area,
|
||||
self->client->area.width +
|
||||
self->size.left + self->size.right,
|
||||
self->client->area.height +
|
||||
self->size.top + self->size.bottom);
|
||||
|
||||
/*
|
||||
// render all the elements
|
||||
int screen = _client->screen();
|
||||
bool focus = _client->focused();
|
||||
if (_decorations & Client::Decor_Titlebar) {
|
||||
render(screen, otk::Size(geom.width, geom.title_height()), _title,
|
||||
&_title_sur, *(focus ? style->titlebarFocusBackground() :
|
||||
style->titlebarUnfocusBackground()), false);
|
||||
|
||||
renderLabel();
|
||||
renderMax();
|
||||
renderDesk();
|
||||
renderIconify();
|
||||
renderIcon();
|
||||
renderClose();
|
||||
}
|
||||
|
||||
if (_decorations & Client::Decor_Handle) {
|
||||
render(screen, otk::Size(geom.width, geom.handle_height), _handle,
|
||||
&_handle_sur, *(focus ? style->handleFocusBackground() :
|
||||
style->handleUnfocusBackground()));
|
||||
render(screen, otk::Size(geom.grip_width(), geom.handle_height), _lgrip,
|
||||
&_grip_sur, *(focus ? style->gripFocusBackground() :
|
||||
style->gripUnfocusBackground()));
|
||||
if ((focus ? style->gripFocusBackground() :
|
||||
style->gripUnfocusBackground())->parentRelative())
|
||||
XSetWindowBackgroundPixmap(**otk::display, _rgrip, ParentRelative);
|
||||
else {
|
||||
XSetWindowBackgroundPixmap(**otk::display, _rgrip, _grip_sur->pixmap());
|
||||
}
|
||||
XClearWindow(**otk::display, _rgrip);
|
||||
}
|
||||
|
||||
XSetWindowBorder(**otk::display, _plate,
|
||||
focus ? style->clientBorderFocusColor()->pixel() :
|
||||
style->clientBorderUnfocusColor()->pixel());
|
||||
|
||||
*/
|
||||
|
||||
frame_adjust_shape(self);
|
||||
}
|
||||
|
||||
void frame_adjust_position(Frame *self)
|
||||
{
|
||||
self->area.x = self->client->area.x;
|
||||
self->area.y = self->client->area.y;
|
||||
frame_client_gravity(self, &self->area.x, &self->area.y);
|
||||
XMoveWindow(ob_display, self->window, self->area.x, self->area.y);
|
||||
}
|
||||
|
||||
void frame_adjust_shape(Frame *self)
|
||||
{
|
||||
#ifdef SHAPE
|
||||
int num;
|
||||
XRectangle xrect[2];
|
||||
|
||||
if (!self->client->shaped) {
|
||||
/* clear the shape on the frame window */
|
||||
XShapeCombineMask(ob_display, self->window, ShapeBounding,
|
||||
self->innersize.left,
|
||||
self->innersize.top,
|
||||
None, ShapeSet);
|
||||
} else {
|
||||
/* make the frame's shape match the clients */
|
||||
XShapeCombineShape(ob_display, self->window, ShapeBounding,
|
||||
self->innersize.left,
|
||||
self->innersize.top,
|
||||
self->client->window, ShapeBounding, ShapeSet);
|
||||
|
||||
num = 0;
|
||||
if (self->decorations & Decor_Titlebar) {
|
||||
xrect[0].x = -self->geom.bevel;
|
||||
xrect[0].y = -self->geom.bevel;
|
||||
xrect[0].width = self->geom.width + self->geom.bwidth * 2;
|
||||
xrect[0].height = self->geom.title_height +
|
||||
self->geom.bwidth * 2;
|
||||
++num;
|
||||
}
|
||||
|
||||
if (self->decorations & Decor_Handle) {
|
||||
xrect[1].x = -self->geom.bevel;
|
||||
xrect[1].y = self->geom.handle_y;
|
||||
xrect[1].width = self->geom.width + self->geom.bwidth * 2;
|
||||
xrect[1].height = self->geom.handle_height +
|
||||
self->geom.bwidth * 2;
|
||||
++num;
|
||||
}
|
||||
|
||||
XShapeCombineRectangles(ob_display, self->window,
|
||||
ShapeBounding, 0, 0, xrect, num,
|
||||
ShapeUnion, Unsorted);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void frame_client_gravity(Frame *self, int *x, int *y)
|
||||
{
|
||||
/* horizontal */
|
||||
switch (self->client->gravity) {
|
||||
default:
|
||||
case NorthWestGravity:
|
||||
case SouthWestGravity:
|
||||
case WestGravity:
|
||||
break;
|
||||
|
||||
case NorthGravity:
|
||||
case SouthGravity:
|
||||
case CenterGravity:
|
||||
*x -= (self->size.left + self->size.right) / 2;
|
||||
break;
|
||||
|
||||
case NorthEastGravity:
|
||||
case SouthEastGravity:
|
||||
case EastGravity:
|
||||
*x -= self->size.left + self->size.right;
|
||||
break;
|
||||
|
||||
case ForgetGravity:
|
||||
case StaticGravity:
|
||||
*x -= self->size.left;
|
||||
break;
|
||||
}
|
||||
|
||||
/* vertical */
|
||||
switch (self->client->gravity) {
|
||||
default:
|
||||
case NorthWestGravity:
|
||||
case NorthEastGravity:
|
||||
case NorthGravity:
|
||||
break;
|
||||
|
||||
case CenterGravity:
|
||||
case EastGravity:
|
||||
case WestGravity:
|
||||
*y -= (self->size.top + self->size.bottom) / 2;
|
||||
break;
|
||||
|
||||
case SouthWestGravity:
|
||||
case SouthEastGravity:
|
||||
case SouthGravity:
|
||||
*y -= self->size.top + self->size.bottom;
|
||||
break;
|
||||
|
||||
case ForgetGravity:
|
||||
case StaticGravity:
|
||||
*y -= self->size.top;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void frame_frame_gravity(Frame *self, int *x, int *y)
|
||||
{
|
||||
/* horizontal */
|
||||
switch (self->client->gravity) {
|
||||
default:
|
||||
case NorthWestGravity:
|
||||
case WestGravity:
|
||||
case SouthWestGravity:
|
||||
break;
|
||||
case NorthGravity:
|
||||
case CenterGravity:
|
||||
case SouthGravity:
|
||||
*x += (self->size.left + self->size.right) / 2;
|
||||
break;
|
||||
case NorthEastGravity:
|
||||
case EastGravity:
|
||||
case SouthEastGravity:
|
||||
*x += self->size.left + self->size.right;
|
||||
break;
|
||||
case StaticGravity:
|
||||
case ForgetGravity:
|
||||
x += self->size.left;
|
||||
break;
|
||||
}
|
||||
|
||||
/* vertical */
|
||||
switch (self->client->gravity) {
|
||||
default:
|
||||
case NorthWestGravity:
|
||||
case WestGravity:
|
||||
case SouthWestGravity:
|
||||
break;
|
||||
case NorthGravity:
|
||||
case CenterGravity:
|
||||
case SouthGravity:
|
||||
*y += (self->size.top + self->size.bottom) / 2;
|
||||
break;
|
||||
case NorthEastGravity:
|
||||
case EastGravity:
|
||||
case SouthEastGravity:
|
||||
*y += self->size.top + self->size.bottom;
|
||||
break;
|
||||
case StaticGravity:
|
||||
case ForgetGravity:
|
||||
*y += self->size.top;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void frame_adjust_state(Frame *self)
|
||||
{
|
||||
/* XXX do shit.. buttons? */
|
||||
}
|
||||
|
||||
void frame_adjust_focus(Frame *self)
|
||||
{
|
||||
/* XXX optimizations later... */
|
||||
frame_adjust_size(self);
|
||||
}
|
||||
|
||||
void frame_adjust_title(Frame *self)
|
||||
{
|
||||
/* XXX optimizations later... */
|
||||
frame_adjust_size(self);
|
||||
}
|
||||
|
||||
void frame_adjust_icon(Frame *self)
|
||||
{
|
||||
/* XXX render icon */
|
||||
}
|
||||
|
||||
GQuark frame_get_context(Client *client, Window win)
|
||||
{
|
||||
Frame *self;
|
||||
|
||||
if (win == ob_root) return g_quark_try_string("root");
|
||||
if (client == NULL) return g_quark_try_string("none");
|
||||
if (win == client->window) return g_quark_try_string("client");
|
||||
|
||||
self = client->frame;
|
||||
if (win == self->window) return g_quark_try_string("frame");
|
||||
if (win == self->plate) return g_quark_try_string("frame");
|
||||
if (win == self->title) return g_quark_try_string("titlebar");
|
||||
if (win == self->label) return g_quark_try_string("titlebar");
|
||||
if (win == self->handle) return g_quark_try_string("handle");
|
||||
if (win == self->lgrip) return g_quark_try_string("blcorner");
|
||||
if (win == self->rgrip) return g_quark_try_string("brcorner");
|
||||
|
||||
return g_quark_try_string("none");
|
||||
}
|
||||
|
||||
void frame_startup(void)
|
||||
{
|
||||
g_quark_from_string("none");
|
||||
g_quark_from_string("root");
|
||||
g_quark_from_string("client");
|
||||
g_quark_from_string("titlebar");
|
||||
g_quark_from_string("handle");
|
||||
g_quark_from_string("frame");
|
||||
g_quark_from_string("blcorner");
|
||||
g_quark_from_string("brcorner");
|
||||
g_quark_from_string("tlcorner");
|
||||
g_quark_from_string("trcorner");
|
||||
g_quark_from_string("foo");
|
||||
}
|
101
c/frame.h
101
c/frame.h
|
@ -1,101 +0,0 @@
|
|||
#ifndef __frame_h
|
||||
#define __frame_h
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include "geom.h"
|
||||
#include "client.h"
|
||||
|
||||
/*! Varius geometry settings in the frame decorations */
|
||||
typedef struct {
|
||||
int width; /* title and handle */
|
||||
int font_height;
|
||||
/* int title_height() { return font_height + bevel*2; } */
|
||||
int title_height;
|
||||
int label_width;
|
||||
/* int label_height() { return font_height; } */
|
||||
int handle_height; /* static, from the style */
|
||||
int icon_x; /* x-position of the window icon button */
|
||||
int title_x; /* x-position of the window title */
|
||||
int iconify_x; /* x-position of the window iconify button */
|
||||
int desktop_x; /* x-position of the window all-desktops button */
|
||||
int max_x; /* x-position of the window maximize button */
|
||||
int close_x; /* x-position of the window close button */
|
||||
int handle_y;
|
||||
int button_size; /* static, from the style */
|
||||
/* int grip_width() { return button_size * 2; } */
|
||||
int grip_width;
|
||||
int bevel; /* static, from the style */
|
||||
int bwidth; /* frame elements' border width */
|
||||
int cbwidth; /* client border width */
|
||||
} FrameGeometry;
|
||||
|
||||
typedef struct Frame {
|
||||
Window window;
|
||||
Window plate;
|
||||
Window title;
|
||||
Window label;
|
||||
Window max;
|
||||
Window close;
|
||||
Window desk;
|
||||
Window icon;
|
||||
Window iconify;
|
||||
Window handle;
|
||||
Window lgrip;
|
||||
Window rgrip;
|
||||
|
||||
Strut size;
|
||||
Strut innersize;
|
||||
Rect area;
|
||||
FrameGeometry geom;
|
||||
|
||||
Client *client;
|
||||
int decorations;
|
||||
|
||||
gboolean visible;
|
||||
} Frame;
|
||||
|
||||
Frame *frame_new(struct Client *client);
|
||||
void frame_free(Frame *self);
|
||||
|
||||
void frame_grab_client(Frame *self);
|
||||
void frame_release_client(Frame *self);
|
||||
|
||||
/*! Update the frame's size to match the client */
|
||||
void frame_adjust_size(Frame *self);
|
||||
/*! Update the frame's position to match the client */
|
||||
void frame_adjust_position(Frame *self);
|
||||
/*! Shape the frame window to the client window */
|
||||
void frame_adjust_shape(Frame *self);
|
||||
/*! Update the frame to match the client's new state (for things like toggle
|
||||
buttons, focus, and the title) XXX break this up */
|
||||
void frame_adjust_state(Frame *self);
|
||||
/*! Update the frame to match the client's focused state */
|
||||
void frame_adjust_focus(Frame *self);
|
||||
/*! Update the frame to display the client's current title */
|
||||
void frame_adjust_title(Frame *self);
|
||||
/*! Update the frame to display the client's current icon */
|
||||
void frame_adjust_icon(Frame *self);
|
||||
|
||||
/*! Applies gravity to the client's position to find where the frame should
|
||||
be positioned.
|
||||
@return The proper coordinates for the frame, based on the client.
|
||||
*/
|
||||
void frame_client_gravity(Frame *self, int *x, int *y);
|
||||
|
||||
/*! Reversly applies gravity to the frame's position to find where the client
|
||||
should be positioned.
|
||||
@return The proper coordinates for the client, based on the frame.
|
||||
*/
|
||||
void frame_frame_gravity(Frame *self, int *x, int *y);
|
||||
|
||||
/*! Shows the frame */
|
||||
void frame_show(Frame *self);
|
||||
/*! Hides the frame */
|
||||
void frame_hide(Frame *self);
|
||||
|
||||
/*! inits quarks - this will go in engines later */
|
||||
void frame_startup(void);
|
||||
|
||||
GQuark frame_get_context(Client *client, Window win);
|
||||
|
||||
#endif
|
53
c/geom.h
53
c/geom.h
|
@ -1,53 +0,0 @@
|
|||
#ifndef __geom_h
|
||||
#define __geom_h
|
||||
|
||||
#ifdef HAVE_ASSERT_H
|
||||
# include <assert.h>
|
||||
#endif
|
||||
|
||||
typedef struct Point {
|
||||
int x;
|
||||
int y;
|
||||
} Point;
|
||||
|
||||
#define POINT_SET(pt, nx, ny) {pt.x = nx; pt.y = ny;}
|
||||
|
||||
typedef struct Size {
|
||||
int width;
|
||||
int height;
|
||||
} Size;
|
||||
|
||||
#define SIZE_SET(sz, w, h) {sz.width = w; sz.height = h;}
|
||||
|
||||
typedef struct Rect {
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
} Rect;
|
||||
|
||||
#define RECT_SET_POINT(r, nx, ny) \
|
||||
{r.x = ny; r.y = ny;}
|
||||
#define RECT_SET_SIZE(r, w, h) \
|
||||
{r.width = w; r.height = h;}
|
||||
#define RECT_SET(r, nx, ny, w, h) \
|
||||
{r.x = nx; r.y = ny; r.width = w; r.height = h;}
|
||||
|
||||
#define RECT_EQUAL(r1, r2) (r1.x == r2.x && r1.y == r2.y && \
|
||||
r1.width == r2.width && r1.height == r2.height)
|
||||
|
||||
typedef struct Strut {
|
||||
int left;
|
||||
int top;
|
||||
int right;
|
||||
int bottom;
|
||||
} Strut;
|
||||
|
||||
#define STRUT_SET(s, l, t, r, b) \
|
||||
{s.left = l; s.top = t; s.right = r; s.bottom = b; }
|
||||
|
||||
#define STRUT_ADD(s1, s2) \
|
||||
{s1.left = MAX(s1.left, s2.left); s1.right = MAX(s1.right, s2.right); \
|
||||
s1.top = MAX(s1.top, s2.top); s1.bottom = MAX(s1.bottom, s2.bottom); }
|
||||
|
||||
#endif
|
73
c/gettext.h
73
c/gettext.h
|
@ -1,73 +0,0 @@
|
|||
/* Convenience header for conditional use of GNU <libintl.h>.
|
||||
Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Library General Public License as published
|
||||
by the Free Software Foundation; either version 2, 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
|
||||
Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
USA. */
|
||||
|
||||
#ifndef _LIBGETTEXT_H
|
||||
#define _LIBGETTEXT_H 1
|
||||
|
||||
|
||||
/* NLS can be disabled through the configure --disable-nls option. */
|
||||
#if ENABLE_NLS
|
||||
|
||||
/* Get declarations of GNU message catalog functions. */
|
||||
# include <libintl.h>
|
||||
|
||||
#else
|
||||
|
||||
/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
|
||||
chokes if dcgettext is defined as a macro. So include it now, to make
|
||||
later inclusions of <locale.h> a NOP. We don't include <libintl.h>
|
||||
as well because people using "gettext.h" will not include <libintl.h>,
|
||||
and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
|
||||
is OK. */
|
||||
#if defined(__sun)
|
||||
# include <locale.h>
|
||||
#endif
|
||||
|
||||
/* Disabled NLS.
|
||||
The casts to 'const char *' serve the purpose of producing warnings
|
||||
for invalid uses of the value returned from these functions.
|
||||
On pre-ANSI systems without 'const', the config.h file is supposed to
|
||||
contain "#define const". */
|
||||
# define gettext(Msgid) ((const char *) (Msgid))
|
||||
# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
|
||||
# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
|
||||
# define ngettext(Msgid1, Msgid2, N) \
|
||||
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
|
||||
# define dngettext(Domainname, Msgid1, Msgid2, N) \
|
||||
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
|
||||
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
|
||||
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
|
||||
# define textdomain(Domainname) ((const char *) (Domainname))
|
||||
# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
|
||||
# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
|
||||
|
||||
#endif
|
||||
|
||||
/* A pseudo function call that serves as a marker for the automated
|
||||
extraction of messages, but does not call gettext(). The run-time
|
||||
translation is done at a different place in the code.
|
||||
The argument, String, should be a literal string. Concatenated strings
|
||||
and other string expressions won't work.
|
||||
The macro's expansion is not parenthesized, so that it is suitable as
|
||||
initializer for static 'char[]' or 'const char[]' variables. */
|
||||
#define gettext_noop(String) String
|
||||
|
||||
/* Custom macro to make life easier */
|
||||
#define _(str) gettext(str)
|
||||
|
||||
#endif /* _LIBGETTEXT_H */
|
285
c/hooks.c
285
c/hooks.c
|
@ -1,285 +0,0 @@
|
|||
#include "hooks.h"
|
||||
#include <Python.h>
|
||||
#include <glib.h>
|
||||
|
||||
/* the 'hooks' module and its dictionary */
|
||||
static PyObject *hooks = NULL, *hooksdict = NULL;
|
||||
|
||||
/*
|
||||
*
|
||||
* Define the type 'Hook'
|
||||
*
|
||||
*/
|
||||
#define IS_HOOK(v) ((v)->ob_type == &HookType)
|
||||
|
||||
staticforward PyTypeObject HookType;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
GSList *funcs;
|
||||
} HookObject;
|
||||
|
||||
static PyObject *create_Hook(PyObject *self, PyObject *args)
|
||||
{
|
||||
HookObject *hook;
|
||||
char *name;
|
||||
int ret;
|
||||
|
||||
(void) self;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s:Hook", &name))
|
||||
return NULL;
|
||||
|
||||
hook = PyObject_New(HookObject, &HookType);
|
||||
hook->funcs = NULL;
|
||||
|
||||
/* add it to the hooks module */
|
||||
ret = PyDict_SetItemString(hooksdict, name, (PyObject*) hook);
|
||||
Py_DECREF(hook);
|
||||
|
||||
if (ret == -1) {
|
||||
char *s = g_strdup_printf(
|
||||
"Failed to add the hook '%s' to the 'hooks' module", name);
|
||||
PyErr_SetString(PyExc_RuntimeError, s);
|
||||
g_free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static void hook_dealloc(HookObject *self)
|
||||
{
|
||||
GSList *it;
|
||||
|
||||
for (it = self->funcs; it != NULL; it = it->next)
|
||||
Py_DECREF((PyObject*) it->data);
|
||||
|
||||
PyObject_Del((PyObject*) self);
|
||||
}
|
||||
|
||||
static PyObject *hook_fire(HookObject *self, PyObject *args)
|
||||
{
|
||||
GSList *it;
|
||||
|
||||
if (!IS_HOOK(self)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"descriptor 'fire' requires a 'Hook' object");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (it = self->funcs; it != NULL; it = it->next) {
|
||||
PyObject *ret = PyObject_CallObject(it->data, args);
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *hook_add(HookObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *func;
|
||||
|
||||
if (!IS_HOOK(self)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"descriptor 'add' requires a 'Hook' object");
|
||||
return NULL;
|
||||
}
|
||||
if (!PyArg_ParseTuple(args, "O:add", &func))
|
||||
return NULL;
|
||||
if (!PyCallable_Check(func)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"descriptor 'add' requires a callable argument");
|
||||
return NULL;
|
||||
}
|
||||
self->funcs = g_slist_append(self->funcs, func);
|
||||
Py_INCREF(func);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *hook_remove(HookObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *func;
|
||||
GSList *it;
|
||||
|
||||
if (!IS_HOOK(self)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"descriptor 'remove' requires a 'Hook' object");
|
||||
return NULL;
|
||||
}
|
||||
if (!PyArg_ParseTuple(args, "O:remove", &func))
|
||||
return NULL;
|
||||
if (!PyCallable_Check(func)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"descriptor 'remove' requires a callable argument");
|
||||
return NULL;
|
||||
}
|
||||
it = g_slist_find(self->funcs, func);
|
||||
if (it != NULL) {
|
||||
self->funcs = g_slist_delete_link(self->funcs, it);
|
||||
Py_DECREF(func);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"given callable object was not found in Hook");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject *hook_count(HookObject *self, PyObject *args)
|
||||
{
|
||||
if (!IS_HOOK(self)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"descriptor 'fire' requires a 'Hook' object");
|
||||
return NULL;
|
||||
}
|
||||
if (!PyArg_ParseTuple(args, ":count"))
|
||||
return NULL;
|
||||
|
||||
return PyInt_FromLong(g_slist_length(self->funcs));
|
||||
}
|
||||
|
||||
static PyTypeObject HookType = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0,
|
||||
"Hook",
|
||||
sizeof(HookObject),
|
||||
0,
|
||||
(destructor) hook_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /*tp_hash */
|
||||
};
|
||||
|
||||
static PyMethodDef HookMethods[] = {
|
||||
{"fire", (PyCFunction)hook_fire, METH_VARARGS,
|
||||
"hook.fire() -- Fire the added hook functions for the Hook."},
|
||||
{"add", (PyCFunction)hook_add, METH_VARARGS,
|
||||
"hook.add(func) -- Add a function to the hook." },
|
||||
{"remove", (PyCFunction)hook_remove, METH_VARARGS,
|
||||
"hook.remove(func) -- Remove a function from the hook." },
|
||||
{"count", (PyCFunction)hook_count, METH_VARARGS,
|
||||
"hook.count() -- Return the number of functions in the hook." },
|
||||
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Module initialization/finalization
|
||||
*
|
||||
*/
|
||||
|
||||
/* the "events" hook */
|
||||
static HookObject *events_hook = NULL, *keyboard_hook = NULL,
|
||||
*pointer_hook = NULL;
|
||||
|
||||
static PyMethodDef HooksMethods[] = {
|
||||
{"create", create_Hook, METH_VARARGS,
|
||||
"hooks.create('name') -- Add a hook called 'name' to the hooks module."},
|
||||
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
void hooks_startup()
|
||||
{
|
||||
int ret;
|
||||
|
||||
HookType.ob_type = &PyType_Type;
|
||||
HookType.tp_methods = HookMethods;
|
||||
PyType_Ready(&HookType);
|
||||
|
||||
Py_InitModule("hooks", HooksMethods);
|
||||
|
||||
/* get the hooks module/dict */
|
||||
hooks = PyImport_ImportModule("hooks"); /* new */
|
||||
g_assert(hooks != NULL);
|
||||
hooksdict = PyModule_GetDict(hooks); /* borrowed */
|
||||
g_assert(hooksdict != NULL);
|
||||
|
||||
/* create the "events" hook */
|
||||
events_hook = PyObject_New(HookObject, &HookType);
|
||||
events_hook->funcs = NULL;
|
||||
|
||||
/* add it to the hooks module */
|
||||
ret = PyDict_SetItemString(hooksdict, "events", (PyObject*) events_hook);
|
||||
g_assert(ret == 0);
|
||||
|
||||
/* create the "keyboard" hook */
|
||||
keyboard_hook = PyObject_New(HookObject, &HookType);
|
||||
keyboard_hook->funcs = NULL;
|
||||
|
||||
/* add it to the hooks module */
|
||||
ret = PyDict_SetItemString(hooksdict, "keyboard",
|
||||
(PyObject*) keyboard_hook);
|
||||
g_assert(ret == 0);
|
||||
|
||||
/* create the "pointer" hook */
|
||||
pointer_hook = PyObject_New(HookObject, &HookType);
|
||||
pointer_hook->funcs = NULL;
|
||||
|
||||
/* add it to the hooks module */
|
||||
ret = PyDict_SetItemString(hooksdict, "pointer", (PyObject*) pointer_hook);
|
||||
g_assert(ret == 0);
|
||||
}
|
||||
|
||||
void hooks_shutdown()
|
||||
{
|
||||
Py_DECREF(pointer_hook);
|
||||
Py_DECREF(keyboard_hook);
|
||||
Py_DECREF(events_hook);
|
||||
Py_DECREF(hooks);
|
||||
}
|
||||
|
||||
void hooks_fire(EventData *data)
|
||||
{
|
||||
PyObject *ret, *args;
|
||||
|
||||
g_assert(events_hook != NULL);
|
||||
|
||||
args = Py_BuildValue("(O)", data);
|
||||
ret = hook_fire(events_hook, args);
|
||||
Py_DECREF(args);
|
||||
if (ret == NULL)
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
void hooks_fire_keyboard(EventData *data)
|
||||
{
|
||||
PyObject *ret, *args;
|
||||
|
||||
g_assert(events_hook != NULL);
|
||||
|
||||
args = Py_BuildValue("(O)", data);
|
||||
ret = hook_fire(keyboard_hook, args);
|
||||
Py_DECREF(args);
|
||||
if (ret == NULL)
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
void hooks_fire_pointer(EventData *data)
|
||||
{
|
||||
PyObject *ret, *args;
|
||||
|
||||
g_assert(events_hook != NULL);
|
||||
|
||||
args = Py_BuildValue("(O)", data);
|
||||
ret = hook_fire(pointer_hook, args);
|
||||
Py_DECREF(args);
|
||||
if (ret == NULL)
|
||||
PyErr_Print();
|
||||
}
|
23
c/hooks.h
23
c/hooks.h
|
@ -1,23 +0,0 @@
|
|||
#ifndef __hooks_h
|
||||
#define __hooks_h
|
||||
|
||||
#include "eventdata.h"
|
||||
|
||||
void hooks_startup();
|
||||
void hooks_shutdown();
|
||||
|
||||
void hooks_fire(EventData *data);
|
||||
|
||||
void hooks_fire_keyboard(EventData *data);
|
||||
|
||||
void hooks_fire_pointer(EventData *data);
|
||||
|
||||
#define LOGICALHOOK(type, context, client) \
|
||||
{ EventData *data = eventdata_new_logical(Logical_##type, \
|
||||
context, client); \
|
||||
g_assert(data != NULL); \
|
||||
hooks_fire(data); \
|
||||
eventdata_free(data); \
|
||||
}
|
||||
|
||||
#endif
|
354
c/kbind.c
354
c/kbind.c
|
@ -1,354 +0,0 @@
|
|||
#include "focus.h"
|
||||
#include "openbox.h"
|
||||
#include "hooks.h"
|
||||
#include "kbind.h"
|
||||
|
||||
#include <glib.h>
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
||||
typedef struct KeyBindingTree {
|
||||
guint state;
|
||||
guint key;
|
||||
GList *keylist;
|
||||
|
||||
/* the next binding in the tree at the same level */
|
||||
struct KeyBindingTree *next_sibling;
|
||||
/* the first child of this binding (next binding in a chained sequence).*/
|
||||
struct KeyBindingTree *first_child;
|
||||
} KeyBindingTree;
|
||||
|
||||
|
||||
static KeyBindingTree *firstnode, *curpos;
|
||||
static guint reset_key, reset_state;
|
||||
static gboolean grabbed, user_grabbed;
|
||||
|
||||
guint kbind_translate_modifier(char *str)
|
||||
{
|
||||
if (!strcmp("Mod1", str)) return Mod1Mask;
|
||||
else if (!strcmp("Mod2", str)) return Mod2Mask;
|
||||
else if (!strcmp("Mod3", str)) return Mod3Mask;
|
||||
else if (!strcmp("Mod4", str)) return Mod4Mask;
|
||||
else if (!strcmp("Mod5", str)) return Mod5Mask;
|
||||
else if (!strcmp("C", str)) return ControlMask;
|
||||
else if (!strcmp("S", str)) return ShiftMask;
|
||||
g_warning("Invalid modifier '%s' in binding.", str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gboolean translate(char *str, guint *state, guint *keycode)
|
||||
{
|
||||
char **parsed;
|
||||
char *l;
|
||||
int i;
|
||||
gboolean ret = FALSE;
|
||||
KeySym sym;
|
||||
|
||||
parsed = g_strsplit(str, "-", -1);
|
||||
|
||||
/* first, find the key (last token) */
|
||||
l = NULL;
|
||||
for (i = 0; parsed[i] != NULL; ++i)
|
||||
l = parsed[i];
|
||||
if (l == NULL)
|
||||
goto translation_fail;
|
||||
|
||||
/* figure out the mod mask */
|
||||
*state = 0;
|
||||
for (i = 0; parsed[i] != l; ++i) {
|
||||
guint m = kbind_translate_modifier(parsed[i]);
|
||||
if (!m) goto translation_fail;
|
||||
*state |= m;
|
||||
}
|
||||
|
||||
/* figure out the keycode */
|
||||
sym = XStringToKeysym(l);
|
||||
if (sym == NoSymbol) {
|
||||
g_warning("Invalid key name '%s' in key binding.", l);
|
||||
goto translation_fail;
|
||||
}
|
||||
*keycode = XKeysymToKeycode(ob_display, sym);
|
||||
if (!keycode) {
|
||||
g_warning("Key '%s' does not exist on the display.", l);
|
||||
goto translation_fail;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
translation_fail:
|
||||
g_strfreev(parsed);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void destroytree(KeyBindingTree *tree)
|
||||
{
|
||||
KeyBindingTree *c;
|
||||
|
||||
while (tree) {
|
||||
destroytree(tree->next_sibling);
|
||||
c = tree->first_child;
|
||||
if (c == NULL) {
|
||||
GList *it;
|
||||
for (it = tree->keylist; it != NULL; it = it->next)
|
||||
g_free(it->data);
|
||||
g_list_free(tree->keylist);
|
||||
}
|
||||
g_free(tree);
|
||||
tree = c;
|
||||
}
|
||||
}
|
||||
|
||||
static KeyBindingTree *buildtree(GList *keylist)
|
||||
{
|
||||
GList *it;
|
||||
KeyBindingTree *ret = NULL, *p;
|
||||
|
||||
if (g_list_length(keylist) <= 0)
|
||||
return NULL; /* nothing in the list.. */
|
||||
|
||||
for (it = g_list_last(keylist); it != NULL; it = it->prev) {
|
||||
p = ret;
|
||||
ret = g_new(KeyBindingTree, 1);
|
||||
ret->next_sibling = NULL;
|
||||
if (p == NULL) {
|
||||
GList *it;
|
||||
|
||||
/* this is the first built node, the bottom node of the tree */
|
||||
ret->keylist = g_list_copy(keylist); /* shallow copy */
|
||||
for (it = ret->keylist; it != NULL; it = it->next) /* deep copy */
|
||||
it->data = g_strdup(it->data);
|
||||
}
|
||||
ret->first_child = p;
|
||||
if (!translate(it->data, &ret->state, &ret->key)) {
|
||||
destroytree(ret);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void assimilate(KeyBindingTree *node)
|
||||
{
|
||||
KeyBindingTree *a, *b, *tmp, *last;
|
||||
|
||||
if (firstnode == NULL) {
|
||||
/* there are no nodes at this level yet */
|
||||
firstnode = node;
|
||||
} else {
|
||||
a = firstnode;
|
||||
last = a;
|
||||
b = node;
|
||||
while (a) {
|
||||
last = a;
|
||||
if (!(a->state == b->state && a->key == b->key)) {
|
||||
a = a->next_sibling;
|
||||
} else {
|
||||
tmp = b;
|
||||
b = b->first_child;
|
||||
g_free(tmp);
|
||||
a = a->first_child;
|
||||
}
|
||||
}
|
||||
if (!(last->state == b->state && last->key == a->key))
|
||||
last->next_sibling = b;
|
||||
else {
|
||||
last->first_child = b->first_child;
|
||||
g_free(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KeyBindingTree *find(KeyBindingTree *search, gboolean *conflict)
|
||||
{
|
||||
KeyBindingTree *a, *b;
|
||||
|
||||
*conflict = FALSE;
|
||||
|
||||
a = firstnode;
|
||||
b = search;
|
||||
while (a && b) {
|
||||
if (!(a->state == b->state && a->key == b->key)) {
|
||||
a = a->next_sibling;
|
||||
} else {
|
||||
if ((a->first_child == NULL) == (b->first_child == NULL)) {
|
||||
if (a->first_child == NULL) {
|
||||
/* found it! (return the actual node, not the search's) */
|
||||
return a;
|
||||
}
|
||||
} else {
|
||||
*conflict = TRUE;
|
||||
return NULL; /* the chain status' don't match (conflict!) */
|
||||
}
|
||||
b = b->first_child;
|
||||
a = a->first_child;
|
||||
}
|
||||
}
|
||||
return NULL; // it just isn't in here
|
||||
}
|
||||
|
||||
static void grab_keys(gboolean grab)
|
||||
{
|
||||
if (!grab) {
|
||||
XUngrabKey(ob_display, AnyKey, AnyModifier, ob_root);
|
||||
} else {
|
||||
KeyBindingTree *p = firstnode;
|
||||
while (p) {
|
||||
XGrabKey(ob_display, p->key, p->state, ob_root, FALSE,
|
||||
GrabModeAsync, GrabModeSync);
|
||||
p = p->next_sibling;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void reset_chains()
|
||||
{
|
||||
/* XXX kill timer */
|
||||
curpos = NULL;
|
||||
if (grabbed) {
|
||||
grabbed = FALSE;
|
||||
g_message("reset chains. user: %d", user_grabbed);
|
||||
if (!user_grabbed)
|
||||
XUngrabKeyboard(ob_display, CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
void kbind_fire(guint state, guint key, gboolean press)
|
||||
{
|
||||
EventData *data;
|
||||
struct Client *c = focus_client;
|
||||
GQuark context = c != NULL ? g_quark_try_string("client")
|
||||
: g_quark_try_string("root");
|
||||
|
||||
if (user_grabbed) {
|
||||
data = eventdata_new_key(press ? Key_Press : Key_Release,
|
||||
context, c, state, key, NULL);
|
||||
g_assert(data != NULL);
|
||||
hooks_fire_keyboard(data);
|
||||
eventdata_free(data);
|
||||
}
|
||||
|
||||
if (key == reset_key && state == reset_state) {
|
||||
reset_chains();
|
||||
XAllowEvents(ob_display, AsyncKeyboard, CurrentTime);
|
||||
} else {
|
||||
KeyBindingTree *p;
|
||||
if (curpos == NULL)
|
||||
p = firstnode;
|
||||
else
|
||||
p = curpos->first_child;
|
||||
while (p) {
|
||||
if (p->key == key && p->state == state) {
|
||||
if (p->first_child != NULL) { /* part of a chain */
|
||||
/* XXX TIMER */
|
||||
if (!grabbed && !user_grabbed) {
|
||||
/*grab should never fail because we should have a sync
|
||||
grab at this point */
|
||||
XGrabKeyboard(ob_display, ob_root, 0, GrabModeAsync,
|
||||
GrabModeSync, CurrentTime);
|
||||
}
|
||||
grabbed = TRUE;
|
||||
curpos = p;
|
||||
XAllowEvents(ob_display, AsyncKeyboard, CurrentTime);
|
||||
} else {
|
||||
data = eventdata_new_key(press ? Key_Press : Key_Release,
|
||||
context, c, state, key,
|
||||
p->keylist);
|
||||
g_assert(data != NULL);
|
||||
hooks_fire(data);
|
||||
eventdata_free(data);
|
||||
|
||||
XAllowEvents(ob_display, AsyncKeyboard, CurrentTime);
|
||||
reset_chains();
|
||||
}
|
||||
break;
|
||||
}
|
||||
p = p->next_sibling;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gboolean kbind_add(GList *keylist)
|
||||
{
|
||||
KeyBindingTree *tree, *t;
|
||||
gboolean conflict;
|
||||
|
||||
if (!(tree = buildtree(keylist)))
|
||||
return FALSE; /* invalid binding requested */
|
||||
|
||||
t = find(tree, &conflict);
|
||||
if (conflict) {
|
||||
/* conflicts with another binding */
|
||||
destroytree(tree);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (t != NULL) {
|
||||
/* already bound to something */
|
||||
destroytree(tree);
|
||||
} else {
|
||||
/* grab the server here to make sure no key pressed go missed */
|
||||
XGrabServer(ob_display);
|
||||
XSync(ob_display, FALSE);
|
||||
|
||||
grab_keys(FALSE);
|
||||
|
||||
/* assimilate this built tree into the main tree */
|
||||
assimilate(tree); // assimilation destroys/uses the tree
|
||||
|
||||
grab_keys(TRUE);
|
||||
|
||||
XUngrabServer(ob_display);
|
||||
XFlush(ob_display);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void kbind_clearall()
|
||||
{
|
||||
grab_keys(FALSE);
|
||||
destroytree(firstnode);
|
||||
firstnode = NULL;
|
||||
grab_keys(TRUE);
|
||||
}
|
||||
|
||||
void kbind_startup()
|
||||
{
|
||||
gboolean b;
|
||||
|
||||
curpos = firstnode = NULL;
|
||||
grabbed = user_grabbed = FALSE;
|
||||
|
||||
b = translate("C-G", &reset_state, &reset_key);
|
||||
g_assert(b);
|
||||
}
|
||||
|
||||
void kbind_shutdown()
|
||||
{
|
||||
if (grabbed || user_grabbed) {
|
||||
grabbed = FALSE;
|
||||
kbind_grab_keyboard(FALSE);
|
||||
}
|
||||
grab_keys(FALSE);
|
||||
destroytree(firstnode);
|
||||
firstnode = NULL;
|
||||
}
|
||||
|
||||
gboolean kbind_grab_keyboard(gboolean grab)
|
||||
{
|
||||
gboolean ret = TRUE;
|
||||
|
||||
if (!grab)
|
||||
g_message("grab_keyboard(false). grabbed: %d", grabbed);
|
||||
|
||||
user_grabbed = grab;
|
||||
if (!grabbed) {
|
||||
if (grab)
|
||||
ret = XGrabKeyboard(ob_display, ob_root, 0, GrabModeAsync,
|
||||
GrabModeAsync, CurrentTime) == GrabSuccess;
|
||||
else
|
||||
XUngrabKeyboard(ob_display, CurrentTime);
|
||||
}
|
||||
return ret;
|
||||
}
|
23
c/kbind.h
23
c/kbind.h
|
@ -1,23 +0,0 @@
|
|||
#ifndef __kbind_h
|
||||
#define __kbind_h
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
void kbind_startup();
|
||||
void kbind_shutdown();
|
||||
|
||||
/*! Adds a new key binding
|
||||
A binding will fail to be added if the binding already exists (as part of
|
||||
a chain or not), or if any of the strings in the keylist are invalid.
|
||||
@return TRUE if the binding could be added; FALSE if it could not.
|
||||
*/
|
||||
gboolean kbind_add(GList *keylist);
|
||||
void kbind_clearall();
|
||||
|
||||
guint kbind_translate_modifier(char *str);
|
||||
|
||||
void kbind_fire(guint state, guint key, gboolean press);
|
||||
|
||||
gboolean kbind_grab_keyboard(gboolean grab);
|
||||
|
||||
#endif
|
220
c/mbind.c
220
c/mbind.c
|
@ -1,220 +0,0 @@
|
|||
#include "mbind.h"
|
||||
#include "kbind.h"
|
||||
#include "frame.h"
|
||||
#include "openbox.h"
|
||||
#include "eventdata.h"
|
||||
#include "hooks.h"
|
||||
|
||||
#include <glib.h>
|
||||
#ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/* GData of GSList*'s of PointerBinding*'s. */
|
||||
static GData *bound_contexts;
|
||||
|
||||
static gboolean grabbed;
|
||||
|
||||
struct mbind_foreach_grab_temp {
|
||||
Client *client;
|
||||
gboolean grab;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
guint state;
|
||||
guint button;
|
||||
char *name;
|
||||
} PointerBinding;
|
||||
|
||||
static gboolean translate(char *str, guint *state, guint *button)
|
||||
{
|
||||
char **parsed;
|
||||
char *l;
|
||||
int i;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
parsed = g_strsplit(str, "-", -1);
|
||||
|
||||
/* first, find the button (last token) */
|
||||
l = NULL;
|
||||
for (i = 0; parsed[i] != NULL; ++i)
|
||||
l = parsed[i];
|
||||
if (l == NULL)
|
||||
goto translation_fail;
|
||||
|
||||
/* figure out the mod mask */
|
||||
*state = 0;
|
||||
for (i = 0; parsed[i] != l; ++i) {
|
||||
guint m = kbind_translate_modifier(parsed[i]);
|
||||
if (!m) goto translation_fail;
|
||||
*state |= m;
|
||||
}
|
||||
|
||||
/* figure out the button */
|
||||
*button = atoi(l);
|
||||
if (!*button) {
|
||||
g_warning("Invalid button '%s' in pointer binding.", l);
|
||||
goto translation_fail;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
translation_fail:
|
||||
g_strfreev(parsed);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void grab_button(Client *client, guint state, guint button, GQuark context,
|
||||
gboolean grab)
|
||||
{
|
||||
Window win;
|
||||
int mode = GrabModeAsync;
|
||||
unsigned int mask;
|
||||
|
||||
if (context == g_quark_try_string("frame")) {
|
||||
win = client->frame->window;
|
||||
mask = ButtonPressMask | ButtonMotionMask | ButtonReleaseMask;
|
||||
} else if (context == g_quark_try_string("client")) {
|
||||
win = client->frame->plate;
|
||||
mode = GrabModeSync; /* this is handled in mbind_fire */
|
||||
mask = ButtonPressMask; /* can't catch more than this with Sync mode
|
||||
the release event is manufactured in
|
||||
mbind_fire */
|
||||
} else return;
|
||||
|
||||
if (grab)
|
||||
XGrabButton(ob_display, button, state, win, FALSE, mask, mode,
|
||||
GrabModeAsync, None, None);
|
||||
else
|
||||
XUngrabButton(ob_display, button, state, win);
|
||||
}
|
||||
|
||||
static void mbind_foreach_grab(GQuark key, gpointer data, gpointer user_data)
|
||||
{
|
||||
struct mbind_foreach_grab_temp *d = user_data;
|
||||
PointerBinding *b = ((GSList *)data)->data;
|
||||
if (b != NULL)
|
||||
grab_button(d->client, b->state, b->button, key, d->grab);
|
||||
}
|
||||
|
||||
void mbind_grab_all(Client *client, gboolean grab)
|
||||
{
|
||||
struct mbind_foreach_grab_temp bt;
|
||||
bt.client = client;
|
||||
bt.grab = grab;
|
||||
g_datalist_foreach(&bound_contexts, mbind_foreach_grab, &bt);
|
||||
}
|
||||
|
||||
void grab_all_clients(gboolean grab)
|
||||
{
|
||||
GSList *it;
|
||||
|
||||
for (it = client_list; it != NULL; it = it->next)
|
||||
mbind_grab_all(it->data, grab);
|
||||
}
|
||||
|
||||
void mbind_startup()
|
||||
{
|
||||
grabbed = FALSE;
|
||||
g_datalist_init(&bound_contexts);
|
||||
}
|
||||
|
||||
void mbind_shutdown()
|
||||
{
|
||||
if (grabbed)
|
||||
mbind_grab_pointer(FALSE);
|
||||
mbind_clearall();
|
||||
g_datalist_clear(&bound_contexts);
|
||||
}
|
||||
|
||||
gboolean mbind_add(char *name, GQuark context)
|
||||
{
|
||||
guint state, button;
|
||||
PointerBinding *b;
|
||||
GSList *it;
|
||||
|
||||
if (!translate(name, &state, &button))
|
||||
return FALSE;
|
||||
|
||||
for (it = g_datalist_id_get_data(&bound_contexts, context);
|
||||
it != NULL; it = it->next){
|
||||
b = it->data;
|
||||
if (b->state == state && b->button == button)
|
||||
return TRUE; /* already bound */
|
||||
}
|
||||
|
||||
grab_all_clients(FALSE);
|
||||
|
||||
/* add the binding */
|
||||
b = g_new(PointerBinding, 1);
|
||||
b->state = state;
|
||||
b->button = button;
|
||||
b->name = g_strdup(name);
|
||||
g_datalist_id_set_data(&bound_contexts, context,
|
||||
g_slist_append(g_datalist_id_get_data(&bound_contexts, context), b));
|
||||
grab_all_clients(TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void mbind_foreach_clear(GQuark key, gpointer data, gpointer user_data)
|
||||
{
|
||||
GSList *it;
|
||||
user_data = user_data;
|
||||
for (it = data; it != NULL; it = it->next) {
|
||||
PointerBinding *b = it->data;
|
||||
g_free(b->name);
|
||||
g_free(b);
|
||||
}
|
||||
g_slist_free(data);
|
||||
}
|
||||
void mbind_clearall()
|
||||
{
|
||||
grab_all_clients(FALSE);
|
||||
g_datalist_foreach(&bound_contexts, mbind_foreach_clear, NULL);
|
||||
}
|
||||
|
||||
void mbind_fire(guint state, guint button, GQuark context, EventType type,
|
||||
Client *client, int xroot, int yroot)
|
||||
{
|
||||
GSList *it;
|
||||
|
||||
if (grabbed) {
|
||||
EventData *data;
|
||||
data = eventdata_new_pointer(type, context, client, state, button,
|
||||
NULL, xroot, yroot);
|
||||
g_assert(data != NULL);
|
||||
hooks_fire_pointer(data);
|
||||
eventdata_free(data);
|
||||
return;
|
||||
}
|
||||
|
||||
for (it = g_datalist_id_get_data(&bound_contexts, context);
|
||||
it != NULL; it = it->next){
|
||||
PointerBinding *b = it->data;
|
||||
if (b->state == state && b->button == button) {
|
||||
EventData *data;
|
||||
data = eventdata_new_pointer(type, context, client, state, button,
|
||||
b->name, xroot, yroot);
|
||||
g_assert(data != NULL);
|
||||
hooks_fire(data);
|
||||
eventdata_free(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gboolean mbind_grab_pointer(gboolean grab)
|
||||
{
|
||||
gboolean ret = TRUE;
|
||||
if (grab)
|
||||
ret = XGrabPointer(ob_display, ob_root, FALSE, (ButtonPressMask |
|
||||
ButtonReleaseMask |
|
||||
ButtonMotionMask |
|
||||
PointerMotionMask),
|
||||
GrabModeAsync, GrabModeAsync, None, None,
|
||||
CurrentTime) == GrabSuccess;
|
||||
else
|
||||
XUngrabPointer(ob_display, CurrentTime);
|
||||
return ret;
|
||||
}
|
21
c/mbind.h
21
c/mbind.h
|
@ -1,21 +0,0 @@
|
|||
#ifndef __mbind_h
|
||||
#define __mbind_h
|
||||
|
||||
#include "obexport.h"
|
||||
#include "client.h"
|
||||
#include <glib.h>
|
||||
|
||||
void mbind_startup();
|
||||
void mbind_shutdown();
|
||||
|
||||
/*! Adds a new pointer binding */
|
||||
gboolean mbind_add(char *name, GQuark context);
|
||||
void mbind_clearall();
|
||||
|
||||
void mbind_fire(guint state, guint button, GQuark context, EventType type,
|
||||
Client *client, int xroot, int yroot);
|
||||
|
||||
void mbind_grab_all(Client *client, gboolean grab);
|
||||
gboolean mbind_grab_pointer(gboolean grab);
|
||||
|
||||
#endif
|
116
c/obexport.c
116
c/obexport.c
|
@ -1,116 +0,0 @@
|
|||
#include "obexport.h"
|
||||
#include <Python.h>
|
||||
#include <glib.h>
|
||||
|
||||
static PyMethodDef obMethods[] = {
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
#define ADD_INT_CONST(n) (PyModule_AddIntConstant(ob, #n, n))
|
||||
|
||||
void obexport_startup()
|
||||
{
|
||||
PyObject *ob, *obdict;
|
||||
|
||||
Py_InitModule("ob", obMethods);
|
||||
|
||||
/* get the ob module/dict */
|
||||
ob = PyImport_ImportModule("ob"); /* new */
|
||||
g_assert(ob != NULL);
|
||||
obdict = PyModule_GetDict(ob); /* borrowed */
|
||||
g_assert(obdict != NULL);
|
||||
|
||||
/* define all the constants! */
|
||||
|
||||
/* State */
|
||||
ADD_INT_CONST(State_Starting);
|
||||
ADD_INT_CONST(State_Exiting);
|
||||
ADD_INT_CONST(State_Running);
|
||||
|
||||
/* Corner */
|
||||
ADD_INT_CONST(Corner_TopLeft);
|
||||
ADD_INT_CONST(Corner_TopRight);
|
||||
ADD_INT_CONST(Corner_BottomLeft);
|
||||
ADD_INT_CONST(Corner_BottomRight);
|
||||
|
||||
/* Orientation */
|
||||
ADD_INT_CONST(Orientation_Horz);
|
||||
ADD_INT_CONST(Orientation_Vert);
|
||||
|
||||
/* Gravity */
|
||||
ADD_INT_CONST(Gravity_Forget);
|
||||
ADD_INT_CONST(Gravity_NE);
|
||||
ADD_INT_CONST(Gravity_N);
|
||||
ADD_INT_CONST(Gravity_NW);
|
||||
ADD_INT_CONST(Gravity_W);
|
||||
ADD_INT_CONST(Gravity_SW);
|
||||
ADD_INT_CONST(Gravity_S);
|
||||
ADD_INT_CONST(Gravity_SE);
|
||||
ADD_INT_CONST(Gravity_E);
|
||||
ADD_INT_CONST(Gravity_Center);
|
||||
ADD_INT_CONST(Gravity_Static);
|
||||
|
||||
/* WindowType */
|
||||
ADD_INT_CONST(Type_Desktop);
|
||||
ADD_INT_CONST(Type_Dock);
|
||||
ADD_INT_CONST(Type_Toolbar);
|
||||
ADD_INT_CONST(Type_Menu);
|
||||
ADD_INT_CONST(Type_Utility);
|
||||
ADD_INT_CONST(Type_Splash);
|
||||
ADD_INT_CONST(Type_Dialog);
|
||||
ADD_INT_CONST(Type_Normal);
|
||||
|
||||
/* Function */
|
||||
ADD_INT_CONST(Func_Resize);
|
||||
ADD_INT_CONST(Func_Move);
|
||||
ADD_INT_CONST(Func_Iconify);
|
||||
ADD_INT_CONST(Func_Maximize);
|
||||
ADD_INT_CONST(Func_Shade);
|
||||
ADD_INT_CONST(Func_Fullscreen);
|
||||
ADD_INT_CONST(Func_Close);
|
||||
|
||||
/* Decoration */
|
||||
ADD_INT_CONST(Decor_Titlebar);
|
||||
ADD_INT_CONST(Decor_Handle);
|
||||
ADD_INT_CONST(Decor_Border);
|
||||
ADD_INT_CONST(Decor_Icon);
|
||||
ADD_INT_CONST(Decor_Iconify);
|
||||
ADD_INT_CONST(Decor_Maximize);
|
||||
ADD_INT_CONST(Decor_AllDesktops);
|
||||
ADD_INT_CONST(Decor_Close);
|
||||
|
||||
/* StackLayer */
|
||||
ADD_INT_CONST(Layer_Icon);
|
||||
ADD_INT_CONST(Layer_Desktop);
|
||||
ADD_INT_CONST(Layer_Below);
|
||||
ADD_INT_CONST(Layer_Normal);
|
||||
ADD_INT_CONST(Layer_Above);
|
||||
ADD_INT_CONST(Layer_Top);
|
||||
ADD_INT_CONST(Layer_Fullscreen);
|
||||
ADD_INT_CONST(Layer_Internal);
|
||||
|
||||
/* EventType */
|
||||
ADD_INT_CONST(Logical_EnterWindow);
|
||||
ADD_INT_CONST(Logical_LeaveWindow);
|
||||
ADD_INT_CONST(Logical_NewWindow);
|
||||
ADD_INT_CONST(Logical_CloseWindow);
|
||||
ADD_INT_CONST(Logical_Startup);
|
||||
ADD_INT_CONST(Logical_Shutdown);
|
||||
ADD_INT_CONST(Logical_RequestActivate);
|
||||
ADD_INT_CONST(Logical_Focus);
|
||||
ADD_INT_CONST(Logical_Bell);
|
||||
ADD_INT_CONST(Logical_UrgentWindow);
|
||||
ADD_INT_CONST(Logical_WindowShow);
|
||||
ADD_INT_CONST(Logical_WindowHide);
|
||||
ADD_INT_CONST(Pointer_Press);
|
||||
ADD_INT_CONST(Pointer_Release);
|
||||
ADD_INT_CONST(Pointer_Motion);
|
||||
ADD_INT_CONST(Key_Press);
|
||||
ADD_INT_CONST(Key_Release);
|
||||
|
||||
Py_DECREF(ob);
|
||||
}
|
||||
|
||||
void obexport_shutdown()
|
||||
{
|
||||
}
|
74
c/obexport.h
74
c/obexport.h
|
@ -1,74 +0,0 @@
|
|||
#ifndef __obexport_h
|
||||
#define __obexport_h
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
/* Define values which will be exported in the 'ob' module. */
|
||||
|
||||
typedef enum {
|
||||
/*! Occurs when the mouse enters a window */
|
||||
Logical_EnterWindow,
|
||||
/*! Occurs when the mouse enters a window */
|
||||
Logical_LeaveWindow,
|
||||
/*! Occurs when a window is finished being managed, just before it is
|
||||
(possibly) displayed.
|
||||
The python scripts are reponsible for showing the window when this is
|
||||
called if they want it to be shown.
|
||||
*/
|
||||
Logical_NewWindow,
|
||||
/*! Occurs when a window is being unmanaged */
|
||||
Logical_CloseWindow,
|
||||
/*! Occurs when the window manager starts up */
|
||||
Logical_Startup,
|
||||
/*! Occurs when the window manager is shutting down */
|
||||
Logical_Shutdown,
|
||||
/*! Occurs when a client is requesting/requested to be activated (i.e.
|
||||
focused, raised, unshaded) */
|
||||
Logical_RequestActivate,
|
||||
/*! Occurs when the input focus target changes
|
||||
The data.client will be NULL of no client is focused. */
|
||||
Logical_Focus,
|
||||
/*! Occurs when the system is fired through X.
|
||||
The data.client will hold the client associated with the bell if
|
||||
one has been specified, or NULL. */
|
||||
Logical_Bell,
|
||||
/*! Occurs when a client toggles its urgent status.
|
||||
The client.urgent member can be used to get the status. */
|
||||
Logical_UrgentWindow,
|
||||
/*! Occurs when a client becomes visible */
|
||||
Logical_WindowShow,
|
||||
/*! Occurs when a client becomes non-visible */
|
||||
Logical_WindowHide,
|
||||
/*! Occurs when a pointer button is pressed on a client or its
|
||||
decorations.
|
||||
Note: to get the event for the client's window or for the entire
|
||||
window+decorations, you need to do an mgrab for the window. */
|
||||
Pointer_Press,
|
||||
/*! Occurs when a pointer button is released on a client or its
|
||||
decorations.
|
||||
Note: to get the event for the client's window or for the entire
|
||||
window+decorations, you need to do an mgrab for the window. */
|
||||
Pointer_Release,
|
||||
/*! Occurs when a pointer button is held and the pointer is dragged on a
|
||||
client or its decorations.
|
||||
Note: to get the event for the client's window or for the entire
|
||||
window+decorations, you need to do an mgrab for the window, or an
|
||||
mgrab_pointer (in which case it may not be a drag). */
|
||||
Pointer_Motion,
|
||||
/*! Occurs when a key is pressed.
|
||||
Note: in order to recieve a key event, a kgrab must be done for the
|
||||
key combination, or a kgrab_keyboard.
|
||||
*/
|
||||
Key_Press,
|
||||
/*! Occurs when a key is released.
|
||||
Note: in order to recieve a key event, a kgrab must be done for the
|
||||
key combination, or a kgrab_keyboard.
|
||||
*/
|
||||
Key_Release
|
||||
} EventType;
|
||||
|
||||
/* create the 'ob' module */
|
||||
void obexport_startup();
|
||||
void obexport_shutdown();
|
||||
|
||||
#endif
|
203
c/openbox.c
203
c/openbox.c
|
@ -1,203 +0,0 @@
|
|||
#include "openbox.h"
|
||||
#include "event.h"
|
||||
#include "client.h"
|
||||
#include "xerror.h"
|
||||
#include "prop.h"
|
||||
#include "screen.h"
|
||||
#include "focus.h"
|
||||
#include "extensions.h"
|
||||
#include "python.h"
|
||||
#include "hooks.h"
|
||||
#include "eventdata.h"
|
||||
#include "gettext.h"
|
||||
#include "clientwrap.h"
|
||||
#include "screenwrap.h"
|
||||
#include "kbind.h"
|
||||
#include "mbind.h"
|
||||
#include "frame.h"
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
# include <sys/select.h>
|
||||
#endif
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
# include <signal.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_WAIT_H
|
||||
# include <sys/types.h>
|
||||
# include <sys/wait.h>
|
||||
#endif
|
||||
#ifdef HAVE_LOCALE_H
|
||||
# include <locale.h>
|
||||
#endif
|
||||
|
||||
#include <X11/cursorfont.h>
|
||||
|
||||
Display *ob_display = NULL;
|
||||
int ob_screen;
|
||||
Window ob_root;
|
||||
State ob_state;
|
||||
gboolean ob_shutdown = FALSE;
|
||||
gboolean ob_restart = FALSE;
|
||||
gboolean ob_remote = FALSE;
|
||||
gboolean ob_sync = TRUE;
|
||||
Cursors ob_cursors;
|
||||
|
||||
void signal_handler(int signal);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct sigaction action;
|
||||
sigset_t sigset;
|
||||
|
||||
ob_state = State_Starting;
|
||||
|
||||
/* initialize the locale */
|
||||
if (!setlocale(LC_ALL, ""))
|
||||
g_warning("Couldn't set locale from environment.\n");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
bind_textdomain_codeset(PACKAGE, "UTF-8");
|
||||
textdomain(PACKAGE);
|
||||
|
||||
/* set up signal handler */
|
||||
sigemptyset(&sigset);
|
||||
action.sa_handler = signal_handler;
|
||||
action.sa_mask = sigset;
|
||||
action.sa_flags = SA_NOCLDSTOP | SA_NODEFER;
|
||||
sigaction(SIGUSR1, &action, (struct sigaction *) NULL);
|
||||
sigaction(SIGPIPE, &action, (struct sigaction *) NULL);
|
||||
sigaction(SIGSEGV, &action, (struct sigaction *) NULL);
|
||||
sigaction(SIGFPE, &action, (struct sigaction *) NULL);
|
||||
sigaction(SIGTERM, &action, (struct sigaction *) NULL);
|
||||
sigaction(SIGINT, &action, (struct sigaction *) NULL);
|
||||
sigaction(SIGHUP, &action, (struct sigaction *) NULL);
|
||||
sigaction(SIGCHLD, &action, (struct sigaction *) NULL);
|
||||
|
||||
/* anything that died while we were restarting won't give us a SIGCHLD */
|
||||
while (waitpid(-1, NULL, WNOHANG) > 0);
|
||||
|
||||
/* XXX parse out command line args */
|
||||
(void)argc;(void)argv;
|
||||
|
||||
/* critical warnings will exit the program */
|
||||
g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL);
|
||||
|
||||
ob_display = XOpenDisplay(NULL);
|
||||
if (ob_display == NULL)
|
||||
/* print a message and exit */
|
||||
g_critical("Failed to open the display.");
|
||||
if (fcntl(ConnectionNumber(ob_display), F_SETFD, 1) == -1)
|
||||
/* print a message and exit */
|
||||
g_critical("Failed to set display as close-on-exec.");
|
||||
|
||||
ob_screen = DefaultScreen(ob_display);
|
||||
ob_root = RootWindow(ob_display, ob_screen);
|
||||
|
||||
/* XXX fork self onto other screens */
|
||||
|
||||
XSynchronize(ob_display, ob_sync);
|
||||
|
||||
/* check for locale support */
|
||||
if (!XSupportsLocale())
|
||||
g_warning("X server does not support locale.");
|
||||
if (!XSetLocaleModifiers(""))
|
||||
g_warning("Cannot set locale modifiers for the X server.");
|
||||
|
||||
/* set our error handler */
|
||||
XSetErrorHandler(xerror_handler);
|
||||
|
||||
/* set the DISPLAY environment variable for any lauched children, to the
|
||||
display we're using, so they open in the right place. */
|
||||
putenv(g_strdup_printf("DISPLAY=%s", DisplayString(ob_display)));
|
||||
|
||||
ob_cursors.left_ptr = XCreateFontCursor(ob_display, XC_left_ptr);
|
||||
ob_cursors.ll_angle = XCreateFontCursor(ob_display, XC_ll_angle);
|
||||
ob_cursors.lr_angle = XCreateFontCursor(ob_display, XC_lr_angle);
|
||||
|
||||
prop_init(); /* get atoms values for the display */
|
||||
extensions_query_all(); /* find which extensions are present */
|
||||
|
||||
if (screen_annex()) { /* it will be ours! */
|
||||
frame_startup();
|
||||
python_startup();
|
||||
obexport_startup();
|
||||
hooks_startup();
|
||||
screenwrap_startup();
|
||||
clientwrap_startup();
|
||||
eventdata_startup();
|
||||
event_startup();
|
||||
screen_startup();
|
||||
focus_startup();
|
||||
client_startup();
|
||||
kbind_startup();
|
||||
mbind_startup();
|
||||
|
||||
/* load the user's settings */
|
||||
if (!python_import("rc"))
|
||||
g_warning("ERROR LOADING RC FILE");
|
||||
|
||||
LOGICALHOOK(Startup, g_quark_try_string("none"), NULL);
|
||||
|
||||
/* get all the existing windows */
|
||||
client_manage_all();
|
||||
|
||||
ob_state = State_Running;
|
||||
while (!ob_shutdown) {
|
||||
event_loop();
|
||||
}
|
||||
ob_state = State_Exiting;
|
||||
|
||||
client_unmanage_all();
|
||||
|
||||
LOGICALHOOK(Shutdown, g_quark_try_string("none"), NULL);
|
||||
|
||||
mbind_shutdown();
|
||||
kbind_shutdown();
|
||||
client_shutdown();
|
||||
screen_shutdown();
|
||||
event_shutdown();
|
||||
eventdata_shutdown();
|
||||
clientwrap_shutdown();
|
||||
screenwrap_shutdown();
|
||||
hooks_shutdown();
|
||||
obexport_shutdown();
|
||||
python_shutdown();
|
||||
}
|
||||
|
||||
XCloseDisplay(ob_display);
|
||||
|
||||
/* XXX if (ob_restart) */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void signal_handler(int signal)
|
||||
{
|
||||
switch (signal) {
|
||||
case SIGUSR1:
|
||||
g_message("Caught SIGUSR1 signal. Restarting.");
|
||||
ob_shutdown = ob_restart = TRUE;
|
||||
break;
|
||||
|
||||
case SIGCHLD:
|
||||
wait(NULL);
|
||||
break;
|
||||
|
||||
case SIGHUP:
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
case SIGPIPE:
|
||||
g_message("Caught signal %d. Exiting.", signal);
|
||||
ob_shutdown = TRUE;
|
||||
break;
|
||||
|
||||
case SIGFPE:
|
||||
case SIGSEGV:
|
||||
g_error("Caught signal %d. Aborting and dumping core.", signal);
|
||||
}
|
||||
}
|
35
c/openbox.h
35
c/openbox.h
|
@ -1,35 +0,0 @@
|
|||
#ifndef __openbox_h
|
||||
#define __openbox_h
|
||||
|
||||
#include "obexport.h"
|
||||
#include <glib.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
/*! The X display */
|
||||
extern Display *ob_display;
|
||||
/*! The number of the screen on which we're running */
|
||||
extern int ob_screen;
|
||||
/*! The root window */
|
||||
extern Window ob_root;
|
||||
|
||||
/* The state of execution of the window manager */
|
||||
State ob_state;
|
||||
|
||||
/*! When set to true, Openbox will exit */
|
||||
extern gboolean ob_shutdown;
|
||||
/*! When set to true, Openbox will restart instead of shutting down */
|
||||
extern gboolean ob_restart;
|
||||
|
||||
/*! Runtime option to specify running on a remote display */
|
||||
extern gboolean ob_remote;
|
||||
/*! Runtime option to run in synchronous mode */
|
||||
extern gboolean ob_sync;
|
||||
|
||||
typedef struct Cursors {
|
||||
Cursor left_ptr;
|
||||
Cursor ll_angle;
|
||||
Cursor lr_angle;
|
||||
} Cursors;
|
||||
Cursors ob_cursors;
|
||||
|
||||
#endif
|
271
c/prop.c
271
c/prop.c
|
@ -1,271 +0,0 @@
|
|||
#include "prop.h"
|
||||
#include "openbox.h"
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
Atoms prop_atoms;
|
||||
|
||||
#define CREATE(var, name) (prop_atoms.var = \
|
||||
XInternAtom(ob_display, name, FALSE))
|
||||
|
||||
void prop_init()
|
||||
{
|
||||
g_assert(ob_display != NULL);
|
||||
|
||||
CREATE(cardinal, "CARDINAL");
|
||||
CREATE(window, "WINDOW");
|
||||
CREATE(pixmap, "PIXMAP");
|
||||
CREATE(atom, "ATOM");
|
||||
CREATE(string, "STRING");
|
||||
CREATE(utf8, "UTF8_STRING");
|
||||
|
||||
CREATE(wm_colormap_windows, "WM_COLORMAP_WINDOWS");
|
||||
CREATE(wm_protocols, "WM_PROTOCOLS");
|
||||
CREATE(wm_state, "WM_STATE");
|
||||
CREATE(wm_change_state, "WM_CHANGE_STATE");
|
||||
CREATE(wm_delete_window, "WM_DELETE_WINDOW");
|
||||
CREATE(wm_take_focus, "WM_TAKE_FOCUS");
|
||||
CREATE(wm_name, "WM_NAME");
|
||||
CREATE(wm_icon_name, "WM_ICON_NAME");
|
||||
CREATE(wm_class, "WM_CLASS");
|
||||
CREATE(wm_window_role, "WM_WINDOW_ROLE");
|
||||
CREATE(motif_wm_hints, "_MOTIF_WM_HINTS");
|
||||
|
||||
CREATE(net_supported, "_NET_SUPPORTED");
|
||||
CREATE(net_client_list, "_NET_CLIENT_LIST");
|
||||
CREATE(net_client_list_stacking, "_NET_CLIENT_LIST_STACKING");
|
||||
CREATE(net_number_of_desktops, "_NET_NUMBER_OF_DESKTOPS");
|
||||
CREATE(net_desktop_geometry, "_NET_DESKTOP_GEOMETRY");
|
||||
CREATE(net_desktop_viewport, "_NET_DESKTOP_VIEWPORT");
|
||||
CREATE(net_current_desktop, "_NET_CURRENT_DESKTOP");
|
||||
CREATE(net_desktop_names, "_NET_DESKTOP_NAMES");
|
||||
CREATE(net_active_window, "_NET_ACTIVE_WINDOW");
|
||||
CREATE(net_workarea, "_NET_WORKAREA");
|
||||
CREATE(net_supporting_wm_check, "_NET_SUPPORTING_WM_CHECK");
|
||||
/* CREATE(net_virtual_roots, "_NET_VIRTUAL_ROOTS"); */
|
||||
CREATE(net_desktop_layout, "_NET_DESKTOP_LAYOUT");
|
||||
CREATE(net_showing_desktop, "_NET_SHOWING_DESKTOP");
|
||||
|
||||
CREATE(net_close_window, "_NET_CLOSE_WINDOW");
|
||||
CREATE(net_wm_moveresize, "_NET_WM_MOVERESIZE");
|
||||
|
||||
/* CREATE(net_properties, "_NET_PROPERTIES"); */
|
||||
CREATE(net_wm_name, "_NET_WM_NAME");
|
||||
CREATE(net_wm_visible_name, "_NET_WM_VISIBLE_NAME");
|
||||
CREATE(net_wm_icon_name, "_NET_WM_ICON_NAME");
|
||||
CREATE(net_wm_visible_icon_name, "_NET_WM_VISIBLE_ICON_NAME");
|
||||
CREATE(net_wm_desktop, "_NET_WM_DESKTOP");
|
||||
CREATE(net_wm_window_type, "_NET_WM_WINDOW_TYPE");
|
||||
CREATE(net_wm_state, "_NET_WM_STATE");
|
||||
CREATE(net_wm_strut, "_NET_WM_STRUT");
|
||||
/* CREATE(net_wm_icon_geometry, "_NET_WM_ICON_GEOMETRY"); */
|
||||
CREATE(net_wm_icon, "_NET_WM_ICON");
|
||||
/* CREATE(net_wm_pid, "_NET_WM_PID"); */
|
||||
/* CREATE(net_wm_handled_icons, "_NET_WM_HANDLED_ICONS"); */
|
||||
CREATE(net_wm_allowed_actions, "_NET_WM_ALLOWED_ACTIONS");
|
||||
|
||||
/* CREATE(net_wm_ping, "_NET_WM_PING"); */
|
||||
|
||||
CREATE(net_wm_window_type_desktop, "_NET_WM_WINDOW_TYPE_DESKTOP");
|
||||
CREATE(net_wm_window_type_dock, "_NET_WM_WINDOW_TYPE_DOCK");
|
||||
CREATE(net_wm_window_type_toolbar, "_NET_WM_WINDOW_TYPE_TOOLBAR");
|
||||
CREATE(net_wm_window_type_menu, "_NET_WM_WINDOW_TYPE_MENU");
|
||||
CREATE(net_wm_window_type_utility, "_NET_WM_WINDOW_TYPE_UTILITY");
|
||||
CREATE(net_wm_window_type_splash, "_NET_WM_WINDOW_TYPE_SPLASH");
|
||||
CREATE(net_wm_window_type_dialog, "_NET_WM_WINDOW_TYPE_DIALOG");
|
||||
CREATE(net_wm_window_type_normal, "_NET_WM_WINDOW_TYPE_NORMAL");
|
||||
|
||||
CREATE(net_wm_moveresize_size_topleft, "_NET_WM_MOVERESIZE_SIZE_TOPLEFT");
|
||||
CREATE(net_wm_moveresize_size_topright,
|
||||
"_NET_WM_MOVERESIZE_SIZE_TOPRIGHT");
|
||||
CREATE(net_wm_moveresize_size_bottomleft,
|
||||
"_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT");
|
||||
CREATE(net_wm_moveresize_size_bottomright,
|
||||
"_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT");
|
||||
CREATE(net_wm_moveresize_move, "_NET_WM_MOVERESIZE_MOVE");
|
||||
|
||||
CREATE(net_wm_action_move, "_NET_WM_ACTION_MOVE");
|
||||
CREATE(net_wm_action_resize, "_NET_WM_ACTION_RESIZE");
|
||||
CREATE(net_wm_action_minimize, "_NET_WM_ACTION_MINIMIZE");
|
||||
CREATE(net_wm_action_shade, "_NET_WM_ACTION_SHADE");
|
||||
CREATE(net_wm_action_stick, "_NET_WM_ACTION_STICK");
|
||||
CREATE(net_wm_action_maximize_horz, "_NET_WM_ACTION_MAXIMIZE_HORZ");
|
||||
CREATE(net_wm_action_maximize_vert, "_NET_WM_ACTION_MAXIMIZE_VERT");
|
||||
CREATE(net_wm_action_fullscreen, "_NET_WM_ACTION_FULLSCREEN");
|
||||
CREATE(net_wm_action_change_desktop, "_NET_WM_ACTION_CHANGE_DESKTOP");
|
||||
CREATE(net_wm_action_close, "_NET_WM_ACTION_CLOSE");
|
||||
CREATE(net_wm_state_modal, "_NET_WM_STATE_MODAL");
|
||||
CREATE(net_wm_state_sticky, "_NET_WM_STATE_STICKY");
|
||||
CREATE(net_wm_state_maximized_vert, "_NET_WM_STATE_MAXIMIZED_VERT");
|
||||
CREATE(net_wm_state_maximized_horz, "_NET_WM_STATE_MAXIMIZED_HORZ");
|
||||
CREATE(net_wm_state_shaded, "_NET_WM_STATE_SHADED");
|
||||
CREATE(net_wm_state_skip_taskbar, "_NET_WM_STATE_SKIP_TASKBAR");
|
||||
CREATE(net_wm_state_skip_pager, "_NET_WM_STATE_SKIP_PAGER");
|
||||
CREATE(net_wm_state_hidden, "_NET_WM_STATE_HIDDEN");
|
||||
CREATE(net_wm_state_fullscreen, "_NET_WM_STATE_FULLSCREEN");
|
||||
CREATE(net_wm_state_above, "_NET_WM_STATE_ABOVE");
|
||||
CREATE(net_wm_state_below, "_NET_WM_STATE_BELOW");
|
||||
|
||||
prop_atoms.net_wm_state_add = 1;
|
||||
prop_atoms.net_wm_state_remove = 0;
|
||||
prop_atoms.net_wm_state_toggle = 2;
|
||||
|
||||
prop_atoms.net_wm_orientation_horz = 0;
|
||||
prop_atoms.net_wm_orientation_vert = 1;
|
||||
prop_atoms.net_wm_topleft = 0;
|
||||
prop_atoms.net_wm_topright = 1;
|
||||
prop_atoms.net_wm_bottomright = 2;
|
||||
prop_atoms.net_wm_bottomleft = 3;
|
||||
|
||||
CREATE(kde_net_system_tray_windows, "_KDE_NET_SYSTEM_TRAY_WINDOWS");
|
||||
CREATE(kde_net_wm_system_tray_window_for,
|
||||
"_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR");
|
||||
CREATE(kde_net_wm_window_type_override,
|
||||
"_KDE_NET_WM_WINDOW_TYPE_OVERRIDE");
|
||||
|
||||
CREATE(kwm_win_icon, "KWM_WIN_ICON");
|
||||
|
||||
CREATE(rootpmapid, "_XROOTPMAP_ID");
|
||||
CREATE(esetrootid, "ESETROOT_PMAP_ID");
|
||||
|
||||
CREATE(openbox_pid, "_OPENBOX_PID");
|
||||
CREATE(openbox_premax, "_OPENBOX_PREMAX");
|
||||
}
|
||||
|
||||
gboolean prop_get(Window win, Atom prop, Atom type, int size,
|
||||
guchar **data, gulong num)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
int res;
|
||||
guchar *xdata = NULL;
|
||||
Atom ret_type;
|
||||
int ret_size;
|
||||
gulong ret_items, bytes_left;
|
||||
long num32 = 32 / size * num; /* num in 32-bit elements */
|
||||
|
||||
res = XGetWindowProperty(ob_display, win, prop, 0l, num32,
|
||||
FALSE, type, &ret_type, &ret_size,
|
||||
&ret_items, &bytes_left, &xdata);
|
||||
if (res == Success && ret_items && xdata) {
|
||||
if (ret_size == size && ret_items >= num) {
|
||||
*data = g_memdup(xdata, num * (size / 8));
|
||||
ret = TRUE;
|
||||
}
|
||||
XFree(xdata);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean prop_get_prealloc(Window win, Atom prop, Atom type, int size,
|
||||
guchar *data, gulong num)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
int res;
|
||||
guchar *xdata = NULL;
|
||||
Atom ret_type;
|
||||
int ret_size;
|
||||
gulong ret_items, bytes_left;
|
||||
long num32 = 32 / size * num; /* num in 32-bit elements */
|
||||
|
||||
res = XGetWindowProperty(ob_display, win, prop, 0l, num32,
|
||||
FALSE, type, &ret_type, &ret_size,
|
||||
&ret_items, &bytes_left, &xdata);
|
||||
if (res == Success && ret_items && xdata) {
|
||||
if (ret_size == size && ret_items >= num) {
|
||||
gulong i;
|
||||
for (i = 0; i < num; ++i)
|
||||
switch (size) {
|
||||
case 8:
|
||||
data[i] = xdata[i];
|
||||
break;
|
||||
case 16:
|
||||
((guint16*)data)[i] = ((guint16*)xdata)[i];
|
||||
break;
|
||||
case 32:
|
||||
((guint32*)data)[i] = ((guint32*)xdata)[i];
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached(); /* unhandled size */
|
||||
}
|
||||
ret = TRUE;
|
||||
}
|
||||
XFree(xdata);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean prop_get_all(Window win, Atom prop, Atom type, int size,
|
||||
guchar **data, gulong *num)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
int res;
|
||||
guchar *xdata = NULL;
|
||||
Atom ret_type;
|
||||
int ret_size;
|
||||
gulong ret_items, bytes_left;
|
||||
|
||||
res = XGetWindowProperty(ob_display, win, prop, 0l, G_MAXLONG,
|
||||
FALSE, type, &ret_type, &ret_size,
|
||||
&ret_items, &bytes_left, &xdata);
|
||||
if (res == Success) {
|
||||
if (ret_size == size && ret_items > 0) {
|
||||
*data = g_memdup(xdata, ret_items * (size / 8));
|
||||
*num = ret_items;
|
||||
ret = TRUE;
|
||||
}
|
||||
XFree(xdata);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean prop_get_string(Window win, Atom prop, Atom type, guchar **data)
|
||||
{
|
||||
guchar *raw;
|
||||
gulong num;
|
||||
GString *str;
|
||||
|
||||
if (prop_get_all(win, prop, type, 8, &raw, &num)) {
|
||||
str = g_string_new_len((char*)raw, num);
|
||||
g_assert(str->str[num] == '\0');
|
||||
|
||||
g_free(raw);
|
||||
|
||||
*data = (guchar*)g_string_free(str, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean prop_get_strings(Window win, Atom prop, Atom type,
|
||||
GPtrArray *data)
|
||||
{
|
||||
guchar *raw;
|
||||
gulong num;
|
||||
GString *str, *str2;
|
||||
guint i, start;
|
||||
|
||||
if (prop_get_all(win, prop, type, 8, &raw, &num)) {
|
||||
str = g_string_new_len((gchar*)raw, num);
|
||||
g_assert(str->str[num] == '\0'); /* assuming this is always true.. */
|
||||
|
||||
g_free(raw);
|
||||
|
||||
/* split it into the list */
|
||||
for (start = 0, i = 0; i < str->len; ++i) {
|
||||
if (str->str[i] == '\0') {
|
||||
str2 = g_string_new_len(&str->str[start], i - start);
|
||||
g_ptr_array_add(data, g_string_free(str2, FALSE));
|
||||
start = i + 1;
|
||||
}
|
||||
}
|
||||
g_string_free(str, TRUE);
|
||||
|
||||
if (data->len > 0)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void prop_erase(Window win, Atom prop)
|
||||
{
|
||||
XDeleteProperty(ob_display, win, prop);
|
||||
}
|
202
c/prop.h
202
c/prop.h
|
@ -1,202 +0,0 @@
|
|||
#ifndef __atoms_h
|
||||
#define __atoms_h
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <glib.h>
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
||||
#include "openbox.h"
|
||||
|
||||
/*! The atoms on the X server which this class will cache */
|
||||
typedef struct Atoms {
|
||||
/* types */
|
||||
Atom cardinal; /*!< The atom which represents the Cardinal data type */
|
||||
Atom window; /*!< The atom which represents window ids */
|
||||
Atom pixmap; /*!< The atom which represents pixmap ids */
|
||||
Atom atom; /*!< The atom which represents atom values */
|
||||
Atom string; /*!< The atom which represents ascii strings */
|
||||
Atom utf8; /*!< The atom which represents utf8-encoded strings */
|
||||
|
||||
/* window hints */
|
||||
Atom wm_colormap_windows;
|
||||
Atom wm_protocols;
|
||||
Atom wm_state;
|
||||
Atom wm_delete_window;
|
||||
Atom wm_take_focus;
|
||||
Atom wm_change_state;
|
||||
Atom wm_name;
|
||||
Atom wm_icon_name;
|
||||
Atom wm_class;
|
||||
Atom wm_window_role;
|
||||
Atom motif_wm_hints;
|
||||
|
||||
/* NETWM atoms */
|
||||
|
||||
/* root window properties */
|
||||
Atom net_supported;
|
||||
Atom net_client_list;
|
||||
Atom net_client_list_stacking;
|
||||
Atom net_number_of_desktops;
|
||||
Atom net_desktop_geometry;
|
||||
Atom net_desktop_viewport;
|
||||
Atom net_current_desktop;
|
||||
Atom net_desktop_names;
|
||||
Atom net_active_window;
|
||||
Atom net_workarea;
|
||||
Atom net_supporting_wm_check;
|
||||
/* Atom net_virtual_roots; */
|
||||
Atom net_desktop_layout;
|
||||
Atom net_showing_desktop;
|
||||
/* root window messages */
|
||||
Atom net_close_window;
|
||||
Atom net_wm_moveresize;
|
||||
/* application window properties */
|
||||
/* Atom net_properties; */
|
||||
Atom net_wm_name;
|
||||
Atom net_wm_visible_name;
|
||||
Atom net_wm_icon_name;
|
||||
Atom net_wm_visible_icon_name;
|
||||
Atom net_wm_desktop;
|
||||
Atom net_wm_window_type;
|
||||
Atom net_wm_state;
|
||||
Atom net_wm_strut;
|
||||
/* Atom net_wm_icon_geometry; */
|
||||
Atom net_wm_icon;
|
||||
/* Atom net_wm_pid; */
|
||||
/* Atom net_wm_handled_icons; */
|
||||
Atom net_wm_allowed_actions;
|
||||
/* application protocols */
|
||||
/* Atom Atom net_wm_ping; */
|
||||
|
||||
Atom net_wm_window_type_desktop;
|
||||
Atom net_wm_window_type_dock;
|
||||
Atom net_wm_window_type_toolbar;
|
||||
Atom net_wm_window_type_menu;
|
||||
Atom net_wm_window_type_utility;
|
||||
Atom net_wm_window_type_splash;
|
||||
Atom net_wm_window_type_dialog;
|
||||
Atom net_wm_window_type_normal;
|
||||
|
||||
Atom net_wm_moveresize_size_topleft;
|
||||
Atom net_wm_moveresize_size_topright;
|
||||
Atom net_wm_moveresize_size_bottomleft;
|
||||
Atom net_wm_moveresize_size_bottomright;
|
||||
Atom net_wm_moveresize_move;
|
||||
|
||||
Atom net_wm_action_move;
|
||||
Atom net_wm_action_resize;
|
||||
Atom net_wm_action_minimize;
|
||||
Atom net_wm_action_shade;
|
||||
Atom net_wm_action_stick;
|
||||
Atom net_wm_action_maximize_horz;
|
||||
Atom net_wm_action_maximize_vert;
|
||||
Atom net_wm_action_fullscreen;
|
||||
Atom net_wm_action_change_desktop;
|
||||
Atom net_wm_action_close;
|
||||
|
||||
Atom net_wm_state_modal;
|
||||
Atom net_wm_state_sticky;
|
||||
Atom net_wm_state_maximized_vert;
|
||||
Atom net_wm_state_maximized_horz;
|
||||
Atom net_wm_state_shaded;
|
||||
Atom net_wm_state_skip_taskbar;
|
||||
Atom net_wm_state_skip_pager;
|
||||
Atom net_wm_state_hidden;
|
||||
Atom net_wm_state_fullscreen;
|
||||
Atom net_wm_state_above;
|
||||
Atom net_wm_state_below;
|
||||
|
||||
Atom net_wm_state_add;
|
||||
Atom net_wm_state_remove;
|
||||
Atom net_wm_state_toggle;
|
||||
|
||||
Atom net_wm_orientation_horz;
|
||||
Atom net_wm_orientation_vert;
|
||||
Atom net_wm_topleft;
|
||||
Atom net_wm_topright;
|
||||
Atom net_wm_bottomright;
|
||||
Atom net_wm_bottomleft;
|
||||
|
||||
/* Extra atoms */
|
||||
|
||||
Atom kde_net_system_tray_windows;
|
||||
Atom kde_net_wm_system_tray_window_for;
|
||||
Atom kde_net_wm_window_type_override;
|
||||
|
||||
Atom kwm_win_icon;
|
||||
|
||||
Atom rootpmapid;
|
||||
Atom esetrootid;
|
||||
|
||||
/* Openbox specific atoms */
|
||||
|
||||
Atom openbox_pid;
|
||||
Atom openbox_premax;
|
||||
} Atoms;
|
||||
Atoms prop_atoms;
|
||||
|
||||
void prop_init();
|
||||
|
||||
gboolean prop_get(Window win, Atom prop, Atom type, int size,
|
||||
guchar **data, gulong num);
|
||||
|
||||
gboolean prop_get_prealloc(Window win, Atom prop, Atom type, int size,
|
||||
guchar *data, gulong num);
|
||||
|
||||
gboolean prop_get_all(Window win, Atom prop, Atom type, int size,
|
||||
guchar **data, gulong *num);
|
||||
|
||||
gboolean prop_get_string(Window win, Atom prop, Atom type, guchar **data);
|
||||
gboolean prop_get_strings(Window win, Atom prop, Atom type,
|
||||
GPtrArray *data);
|
||||
|
||||
void prop_erase(Window win, Atom prop);
|
||||
|
||||
/* Set an 8-bit property from a string */
|
||||
#define PROP_SETS(win, prop, type, value) \
|
||||
(XChangeProperty(ob_display, win, prop_atoms.prop, prop_atoms.type, 8, \
|
||||
PropModeReplace, (guchar*)value, strlen(value)))
|
||||
/* Set a 32-bit property from a single value */
|
||||
#define PROP_SET32(win, prop, type, value) \
|
||||
(XChangeProperty(ob_display, win, prop_atoms.prop, prop_atoms.type, 32, \
|
||||
PropModeReplace, (guchar*)&value, 1))
|
||||
/* Set a 32-bit property from an array */
|
||||
#define PROP_SET32A(win, prop, type, value, num) \
|
||||
(XChangeProperty(ob_display, win, prop_atoms.prop, prop_atoms.type, 32, \
|
||||
PropModeReplace, (guchar*)value, num))
|
||||
|
||||
/* Get an 8-bit property into a string */
|
||||
#define PROP_GETS(win, prop, type, value) \
|
||||
(prop_get_string(win, prop_atoms.prop, prop_atoms.type, \
|
||||
(guchar**)&value))
|
||||
/* Get an 8-bit property into a GPtrArray of strings
|
||||
(The strings must be freed, the GPtrArray must already be created.) */
|
||||
#define PROP_GETSA(win, prop, type, value) \
|
||||
(prop_get_strings(win, prop_atoms.prop, prop_atoms.type, \
|
||||
value))
|
||||
|
||||
/* Get an entire 8-bit property into an array (which must be freed) */
|
||||
#define PROP_GET8U(win, prop, type, value, num) \
|
||||
(prop_get_all(win, prop_atoms.prop, prop_atoms.type, 8, \
|
||||
(guchar**)&value, &num))
|
||||
|
||||
/* Get 1 element of a 32-bit property into a given variable */
|
||||
#define PROP_GET32(win, prop, type, value) \
|
||||
(prop_get_prealloc(win, prop_atoms.prop, prop_atoms.type, 32, \
|
||||
(guchar*)&value, 1))
|
||||
|
||||
/* Get an amount of a 32-bit property into an array (which must be freed) */
|
||||
#define PROP_GET32A(win, prop, type, value, num) \
|
||||
(prop_get(win, prop_atoms.prop, prop_atoms.type, 32, \
|
||||
(guchar**)&value, num))
|
||||
|
||||
/* Get an entire 32-bit property into an array (which must be freed) */
|
||||
#define PROP_GET32U(win, prop, type, value, num) \
|
||||
(prop_get_all(win, prop_atoms.prop, prop_atoms.type, 32, \
|
||||
(guchar**)&value, &num))
|
||||
|
||||
#define PROP_ERASE(win, prop) (prop_erase(win, prop_atoms.prop))
|
||||
|
||||
#endif
|
55
c/python.c
55
c/python.c
|
@ -1,55 +0,0 @@
|
|||
#include <Python.h>
|
||||
#include <glib.h>
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
void python_startup()
|
||||
{
|
||||
PyObject *sys, *sysdict, *syspath, *path1, *path2;
|
||||
char *home, *homescriptdir;
|
||||
|
||||
Py_Initialize();
|
||||
|
||||
/* fix up the system path */
|
||||
|
||||
sys = PyImport_ImportModule((char*)"sys"); /* new */
|
||||
sysdict = PyModule_GetDict(sys); /* borrowed */
|
||||
syspath = PyDict_GetItemString(sysdict, (char*)"path"); /* borrowed */
|
||||
|
||||
path1 = PyString_FromString(SCRIPTDIR); /* new */
|
||||
PyList_Insert(syspath, 0, path1);
|
||||
Py_DECREF(path1);
|
||||
|
||||
home = getenv("HOME");
|
||||
if (home != NULL) {
|
||||
homescriptdir = g_strdup_printf("%s/.openbox", home);
|
||||
path2 = PyString_FromString(homescriptdir); /* new */
|
||||
g_free(homescriptdir);
|
||||
|
||||
PyList_Insert(syspath, 0, path2);
|
||||
Py_DECREF(path2);
|
||||
} else
|
||||
g_warning("Failed to read the $HOME environment variable");
|
||||
|
||||
Py_DECREF(sys);
|
||||
}
|
||||
|
||||
void python_shutdown()
|
||||
{
|
||||
Py_Finalize();
|
||||
}
|
||||
|
||||
gboolean python_import(char *module)
|
||||
{
|
||||
PyObject *mod;
|
||||
|
||||
mod = PyImport_ImportModule(module); /* new */
|
||||
if (mod == NULL) {
|
||||
PyErr_Print();
|
||||
return FALSE;
|
||||
}
|
||||
Py_DECREF(mod);
|
||||
return TRUE;
|
||||
}
|
10
c/python.h
10
c/python.h
|
@ -1,10 +0,0 @@
|
|||
#ifndef __python_h
|
||||
#define __python_h
|
||||
|
||||
void python_startup();
|
||||
void python_shutdown();
|
||||
|
||||
/*! Import a python module */
|
||||
gboolean python_import(char *module);
|
||||
|
||||
#endif
|
516
c/screen.c
516
c/screen.c
|
@ -1,516 +0,0 @@
|
|||
#include "openbox.h"
|
||||
#include "prop.h"
|
||||
#include "screen.h"
|
||||
#include "client.h"
|
||||
#include "focus.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
/*! The event mask to grab on the root window */
|
||||
#define ROOT_EVENTMASK (/*ColormapChangeMask |*/ PropertyChangeMask | \
|
||||
EnterWindowMask | LeaveWindowMask | \
|
||||
SubstructureNotifyMask | SubstructureRedirectMask | \
|
||||
ButtonPressMask | ButtonReleaseMask | ButtonMotionMask)
|
||||
|
||||
guint screen_num_desktops = 1;
|
||||
guint screen_desktop = 0;
|
||||
Size screen_physical_size;
|
||||
gboolean screen_showing_desktop;
|
||||
DesktopLayout screen_desktop_layout;
|
||||
GPtrArray *screen_desktop_names;
|
||||
|
||||
static Rect *area = NULL;
|
||||
static Strut *strut = NULL;
|
||||
|
||||
static void screen_update_area();
|
||||
|
||||
static gboolean running;
|
||||
static int another_running(Display *d, XErrorEvent *e)
|
||||
{
|
||||
(void)d;(void)e;
|
||||
g_message("A window manager is already running on screen %d",
|
||||
ob_screen);
|
||||
running = TRUE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
gboolean screen_annex()
|
||||
{
|
||||
XErrorHandler old;
|
||||
Window support;
|
||||
pid_t pid;
|
||||
int i, num_support;
|
||||
Atom *supported;
|
||||
|
||||
running = FALSE;
|
||||
old = XSetErrorHandler(another_running);
|
||||
XSelectInput(ob_display, ob_root, ROOT_EVENTMASK);
|
||||
XSync(ob_display, FALSE);
|
||||
XSetErrorHandler(old);
|
||||
if (running)
|
||||
return FALSE;
|
||||
|
||||
g_message("Managing screen %d", ob_screen);
|
||||
|
||||
/* set the mouse cursor for the root window (the default cursor) */
|
||||
XDefineCursor(ob_display, ob_root, ob_cursors.left_ptr);
|
||||
|
||||
/* set the OPENBOX_PID hint */
|
||||
pid = getpid();
|
||||
PROP_SET32(ob_root, openbox_pid, cardinal, pid);
|
||||
|
||||
/* create the netwm support window */
|
||||
support = XCreateSimpleWindow(ob_display, ob_root, 0, 0, 1, 1, 0, 0, 0);
|
||||
|
||||
/* set supporting window */
|
||||
PROP_SET32(ob_root, net_supporting_wm_check, window, support);
|
||||
|
||||
/* set properties on the supporting window */
|
||||
PROP_SETS(support, net_wm_name, utf8, "Openbox");
|
||||
PROP_SET32(support, net_supporting_wm_check, window, support);
|
||||
|
||||
/* set the _NET_SUPPORTED_ATOMS hint */
|
||||
num_support = 48;
|
||||
i = 0;
|
||||
supported = g_new(Atom, num_support);
|
||||
supported[i++] = prop_atoms.net_current_desktop;
|
||||
supported[i++] = prop_atoms.net_number_of_desktops;
|
||||
supported[i++] = prop_atoms.net_desktop_geometry;
|
||||
supported[i++] = prop_atoms.net_desktop_viewport;
|
||||
supported[i++] = prop_atoms.net_active_window;
|
||||
supported[i++] = prop_atoms.net_workarea;
|
||||
supported[i++] = prop_atoms.net_client_list;
|
||||
supported[i++] = prop_atoms.net_client_list_stacking;
|
||||
supported[i++] = prop_atoms.net_desktop_names;
|
||||
supported[i++] = prop_atoms.net_close_window;
|
||||
supported[i++] = prop_atoms.net_desktop_layout;
|
||||
supported[i++] = prop_atoms.net_showing_desktop;
|
||||
supported[i++] = prop_atoms.net_wm_name;
|
||||
supported[i++] = prop_atoms.net_wm_visible_name;
|
||||
supported[i++] = prop_atoms.net_wm_icon_name;
|
||||
supported[i++] = prop_atoms.net_wm_visible_icon_name;
|
||||
supported[i++] = prop_atoms.net_wm_desktop;
|
||||
supported[i++] = prop_atoms.net_wm_strut;
|
||||
supported[i++] = prop_atoms.net_wm_window_type;
|
||||
supported[i++] = prop_atoms.net_wm_window_type_desktop;
|
||||
supported[i++] = prop_atoms.net_wm_window_type_dock;
|
||||
supported[i++] = prop_atoms.net_wm_window_type_toolbar;
|
||||
supported[i++] = prop_atoms.net_wm_window_type_menu;
|
||||
supported[i++] = prop_atoms.net_wm_window_type_utility;
|
||||
supported[i++] = prop_atoms.net_wm_window_type_splash;
|
||||
supported[i++] = prop_atoms.net_wm_window_type_dialog;
|
||||
supported[i++] = prop_atoms.net_wm_window_type_normal;
|
||||
supported[i++] = prop_atoms.net_wm_allowed_actions;
|
||||
supported[i++] = prop_atoms.net_wm_action_move;
|
||||
supported[i++] = prop_atoms.net_wm_action_resize;
|
||||
supported[i++] = prop_atoms.net_wm_action_minimize;
|
||||
supported[i++] = prop_atoms.net_wm_action_shade;
|
||||
supported[i++] = prop_atoms.net_wm_action_maximize_horz;
|
||||
supported[i++] = prop_atoms.net_wm_action_maximize_vert;
|
||||
supported[i++] = prop_atoms.net_wm_action_fullscreen;
|
||||
supported[i++] = prop_atoms.net_wm_action_change_desktop;
|
||||
supported[i++] = prop_atoms.net_wm_action_close;
|
||||
supported[i++] = prop_atoms.net_wm_state;
|
||||
supported[i++] = prop_atoms.net_wm_state_modal;
|
||||
supported[i++] = prop_atoms.net_wm_state_maximized_vert;
|
||||
supported[i++] = prop_atoms.net_wm_state_maximized_horz;
|
||||
supported[i++] = prop_atoms.net_wm_state_shaded;
|
||||
supported[i++] = prop_atoms.net_wm_state_skip_taskbar;
|
||||
supported[i++] = prop_atoms.net_wm_state_skip_pager;
|
||||
supported[i++] = prop_atoms.net_wm_state_hidden;
|
||||
supported[i++] = prop_atoms.net_wm_state_fullscreen;
|
||||
supported[i++] = prop_atoms.net_wm_state_above;
|
||||
supported[i++] = prop_atoms.net_wm_state_below;
|
||||
g_assert(i == num_support);
|
||||
/*
|
||||
supported[] = prop_atoms.net_wm_moveresize;
|
||||
supported[] = prop_atoms.net_wm_moveresize_size_topleft;
|
||||
supported[] = prop_atoms.net_wm_moveresize_size_topright;
|
||||
supported[] = prop_atoms.net_wm_moveresize_size_bottomleft;
|
||||
supported[] = prop_atoms.net_wm_moveresize_size_bottomright;
|
||||
supported[] = prop_atoms.net_wm_moveresize_move;
|
||||
supported[] = prop_atoms.net_wm_action_stick;
|
||||
*/
|
||||
|
||||
PROP_SET32A(ob_root, net_supported, atom, supported, num_support);
|
||||
g_free(supported);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void screen_startup()
|
||||
{
|
||||
screen_desktop_names = g_ptr_array_new();
|
||||
|
||||
/* get the initial size */
|
||||
screen_resize();
|
||||
|
||||
screen_set_num_desktops(4);
|
||||
screen_set_desktop(0);
|
||||
|
||||
/* don't start in showing-desktop mode */
|
||||
screen_showing_desktop = FALSE;
|
||||
PROP_SET32(ob_root, net_showing_desktop, cardinal, screen_showing_desktop);
|
||||
|
||||
screen_update_layout();
|
||||
}
|
||||
|
||||
void screen_shutdown()
|
||||
{
|
||||
guint i;
|
||||
for (i = 0; i < screen_desktop_names->len; ++i)
|
||||
g_free(g_ptr_array_index(screen_desktop_names, i));
|
||||
g_ptr_array_free(screen_desktop_names, TRUE);
|
||||
g_free(strut);
|
||||
g_free(area);
|
||||
}
|
||||
|
||||
void screen_resize()
|
||||
{
|
||||
/* Set the _NET_DESKTOP_GEOMETRY hint */
|
||||
/* XXX RandR support here? */
|
||||
int geometry[2];
|
||||
|
||||
geometry[0] = WidthOfScreen(ScreenOfDisplay(ob_display, ob_screen));
|
||||
geometry[1] = HeightOfScreen(ScreenOfDisplay(ob_display, ob_screen));
|
||||
PROP_SET32A(ob_root, net_desktop_geometry, cardinal, geometry, 2);
|
||||
screen_physical_size.width = geometry[0];
|
||||
screen_physical_size.height = geometry[1];
|
||||
|
||||
if (ob_state == State_Starting)
|
||||
return;
|
||||
|
||||
screen_update_struts();
|
||||
|
||||
/* XXX adjust more stuff ? */
|
||||
}
|
||||
|
||||
void screen_set_num_desktops(guint num)
|
||||
{
|
||||
unsigned long *viewport;
|
||||
|
||||
g_assert(num > 0);
|
||||
|
||||
/* move windows on desktops that will no longer exist! */
|
||||
/* XXX
|
||||
std::list<Client*>::iterator it, end = clients.end();
|
||||
for (it = clients.begin(); it != end; ++it) {
|
||||
unsigned int d = (*it)->desktop();
|
||||
if (d >= num && d != 0xffffffff) {
|
||||
XEvent ce;
|
||||
ce.xclient.type = ClientMessage;
|
||||
ce.xclient.message_type = otk::Property::atoms.net_wm_desktop;
|
||||
ce.xclient.display = **otk::display;
|
||||
ce.xclient.window = (*it)->window();
|
||||
ce.xclient.format = 32;
|
||||
ce.xclient.data.l[0] = num - 1;
|
||||
XSendEvent(**otk::display, _info->rootWindow(), false,
|
||||
SubstructureNotifyMask | SubstructureRedirectMask, &ce);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
screen_num_desktops = num;
|
||||
PROP_SET32(ob_root, net_number_of_desktops, cardinal, num);
|
||||
|
||||
/* set the viewport hint */
|
||||
viewport = g_new0(unsigned long, num * 2);
|
||||
PROP_SET32A(ob_root, net_desktop_viewport, cardinal, viewport, num * 2);
|
||||
g_free(viewport);
|
||||
|
||||
/* change our struts/area to match */
|
||||
screen_update_struts();
|
||||
|
||||
/* the number of rows/columns will differ */
|
||||
screen_update_layout();
|
||||
|
||||
/* may be some unnamed desktops that we need to fill in with names */
|
||||
screen_update_desktop_names();
|
||||
|
||||
/* change our desktop if we're on one that no longer exists! */
|
||||
if (screen_desktop >= screen_num_desktops)
|
||||
screen_set_desktop(num - 1);
|
||||
}
|
||||
|
||||
void screen_set_desktop(guint num)
|
||||
{
|
||||
guint old = screen_desktop;
|
||||
|
||||
g_assert(num < screen_num_desktops);
|
||||
|
||||
g_message("Moving to desktop %u", num);
|
||||
|
||||
screen_desktop = num;
|
||||
PROP_SET32(ob_root, net_current_desktop, cardinal, num);
|
||||
|
||||
if (old == num) return;
|
||||
|
||||
/* XXX show/hide all the clients
|
||||
std::list<Client*>::iterator it, end = clients.end();
|
||||
for (it = clients.begin(); it != end; ++it)
|
||||
(*it)->showhide(); */
|
||||
|
||||
/* XXX force the callbacks to fire
|
||||
if (!openbox->focusedClient())
|
||||
openbox->setFocusedClient(0); */
|
||||
}
|
||||
|
||||
void screen_update_layout()
|
||||
{
|
||||
unsigned long *data = NULL;
|
||||
|
||||
/* defaults */
|
||||
screen_desktop_layout.orientation = prop_atoms.net_wm_orientation_horz;
|
||||
screen_desktop_layout.start_corner = prop_atoms.net_wm_topleft;
|
||||
screen_desktop_layout.rows = 1;
|
||||
screen_desktop_layout.columns = screen_num_desktops;
|
||||
|
||||
if (PROP_GET32A(ob_root, net_desktop_layout, cardinal, data, 4)) {
|
||||
if (data[0] == prop_atoms.net_wm_orientation_vert)
|
||||
screen_desktop_layout.orientation = data[0];
|
||||
if (data[3] == prop_atoms.net_wm_topright)
|
||||
screen_desktop_layout.start_corner = data[3];
|
||||
else if (data[3] == prop_atoms.net_wm_bottomright)
|
||||
screen_desktop_layout.start_corner = data[3];
|
||||
else if (data[3] == prop_atoms.net_wm_bottomleft)
|
||||
screen_desktop_layout.start_corner = data[3];
|
||||
|
||||
/* fill in a zero rows/columns */
|
||||
if (!(data[1] == 0 && data[2] == 0)) { /* both 0's is bad data.. */
|
||||
if (data[1] == 0) {
|
||||
data[1] = (screen_num_desktops +
|
||||
screen_num_desktops % data[2]) / data[2];
|
||||
} else if (data[2] == 0) {
|
||||
data[2] = (screen_num_desktops +
|
||||
screen_num_desktops % data[1]) / data[1];
|
||||
}
|
||||
screen_desktop_layout.columns = data[1];
|
||||
screen_desktop_layout.rows = data[2];
|
||||
}
|
||||
|
||||
/* bounds checking */
|
||||
if (screen_desktop_layout.orientation ==
|
||||
prop_atoms.net_wm_orientation_horz) {
|
||||
if (screen_desktop_layout.rows > screen_num_desktops)
|
||||
screen_desktop_layout.rows = screen_num_desktops;
|
||||
if (screen_desktop_layout.columns > ((screen_num_desktops +
|
||||
screen_num_desktops %
|
||||
screen_desktop_layout.rows) /
|
||||
screen_desktop_layout.rows))
|
||||
screen_desktop_layout.columns =
|
||||
(screen_num_desktops + screen_num_desktops %
|
||||
screen_desktop_layout.rows) /
|
||||
screen_desktop_layout.rows;
|
||||
} else {
|
||||
if (screen_desktop_layout.columns > screen_num_desktops)
|
||||
screen_desktop_layout.columns = screen_num_desktops;
|
||||
if (screen_desktop_layout.rows > ((screen_num_desktops +
|
||||
screen_num_desktops %
|
||||
screen_desktop_layout.columns) /
|
||||
screen_desktop_layout.columns))
|
||||
screen_desktop_layout.rows =
|
||||
(screen_num_desktops + screen_num_desktops %
|
||||
screen_desktop_layout.columns) /
|
||||
screen_desktop_layout.columns;
|
||||
}
|
||||
g_free(data);
|
||||
}
|
||||
}
|
||||
|
||||
void screen_update_desktop_names()
|
||||
{
|
||||
guint i;
|
||||
|
||||
/* empty the array */
|
||||
for (i = 0; i < screen_desktop_names->len; ++i)
|
||||
g_free(g_ptr_array_index(screen_desktop_names, i));
|
||||
g_ptr_array_set_size(screen_desktop_names, 0);
|
||||
|
||||
PROP_GETSA(ob_root, net_desktop_names, utf8, screen_desktop_names);
|
||||
|
||||
while (screen_desktop_names->len < screen_num_desktops)
|
||||
g_ptr_array_add(screen_desktop_names, g_strdup("Unnamed Desktop"));
|
||||
}
|
||||
|
||||
void screen_show_desktop(gboolean show)
|
||||
{
|
||||
GSList *it;
|
||||
static Window saved_focus = 0;
|
||||
|
||||
if (show == screen_showing_desktop) return; /* no change */
|
||||
|
||||
/* save the window focus, and restore it when leaving the show-desktop
|
||||
mode */
|
||||
if (show && focus_client)
|
||||
saved_focus = focus_client->window;
|
||||
|
||||
screen_showing_desktop = show;
|
||||
|
||||
for (it = client_list; it; it = g_slist_next(it)) {
|
||||
Client *client = it->data;
|
||||
if (client->type == Type_Desktop) {
|
||||
if (show) client_focus(client);
|
||||
} else
|
||||
client_showhide(client);
|
||||
}
|
||||
|
||||
if (!show) {
|
||||
Client *f = focus_client;
|
||||
if (!f || f->type == Type_Desktop) {
|
||||
Client *c = g_hash_table_lookup(client_map,
|
||||
(gpointer)saved_focus);
|
||||
if (c) client_focus(c);
|
||||
}
|
||||
}
|
||||
|
||||
show = show ? 1 : 0; /* make it boolean */
|
||||
PROP_SET32(ob_root, net_showing_desktop, cardinal, show);
|
||||
}
|
||||
|
||||
void screen_install_colormap(Client *client, gboolean install)
|
||||
{
|
||||
if (client == NULL) {
|
||||
/* XXX DONT USE THE DEFAULT SHIT HERE */
|
||||
if (install)
|
||||
XInstallColormap(ob_display,
|
||||
DefaultColormap(ob_display, ob_screen));
|
||||
else
|
||||
XUninstallColormap(ob_display,
|
||||
DefaultColormap(ob_display, ob_screen));
|
||||
} else {
|
||||
XWindowAttributes wa;
|
||||
if (XGetWindowAttributes(ob_display, client->window, &wa)) {
|
||||
if (install)
|
||||
XInstallColormap(ob_display, wa.colormap);
|
||||
else
|
||||
XUninstallColormap(ob_display, wa.colormap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void screen_update_struts()
|
||||
{
|
||||
GSList *it;
|
||||
guint i;
|
||||
|
||||
if (strut != NULL)
|
||||
g_free(strut);
|
||||
strut = g_new0(Strut, screen_num_desktops + 1);
|
||||
|
||||
for (it = client_list; it; it = it->next) {
|
||||
Client *c = it->data;
|
||||
if (c->iconic) continue; /* these dont count in the strut */
|
||||
|
||||
if (c->desktop == 0xffffffff) {
|
||||
for (i = 0; i < screen_num_desktops; ++i)
|
||||
STRUT_ADD(strut[i], c->strut);
|
||||
} else {
|
||||
g_assert(c->desktop < screen_num_desktops);
|
||||
STRUT_ADD(strut[c->desktop], c->strut);
|
||||
}
|
||||
/* apply to the 'all desktops' strut */
|
||||
STRUT_ADD(strut[screen_num_desktops], c->strut);
|
||||
}
|
||||
screen_update_area();
|
||||
}
|
||||
|
||||
static void screen_update_area()
|
||||
{
|
||||
guint i;
|
||||
gulong *dims;
|
||||
|
||||
if (area != NULL)
|
||||
g_free(area);
|
||||
area = g_new0(Rect, screen_num_desktops + 1);
|
||||
|
||||
dims = g_new(unsigned long, 4 * screen_num_desktops);
|
||||
for (i = 0; i < screen_num_desktops + 1; ++i) {
|
||||
Rect old_area = area[i];
|
||||
/*
|
||||
#ifdef XINERAMA
|
||||
// reset to the full areas
|
||||
if (isXineramaActive())
|
||||
xineramaUsableArea = getXineramaAreas();
|
||||
#endif // XINERAMA
|
||||
*/
|
||||
|
||||
RECT_SET(area[i], strut[i].left, strut[i].top,
|
||||
screen_physical_size.width - (strut[i].left +
|
||||
strut[i].right),
|
||||
screen_physical_size.height - (strut[i].top +
|
||||
strut[i].bottom));
|
||||
|
||||
/*
|
||||
#ifdef XINERAMA
|
||||
if (isXineramaActive()) {
|
||||
// keep each of the ximerama-defined areas inside the strut
|
||||
RectList::iterator xit, xend = xineramaUsableArea.end();
|
||||
for (xit = xineramaUsableArea.begin(); xit != xend; ++xit) {
|
||||
if (xit->x() < usableArea.x()) {
|
||||
xit->setX(usableArea.x());
|
||||
xit->setWidth(xit->width() - usableArea.x());
|
||||
}
|
||||
if (xit->y() < usableArea.y()) {
|
||||
xit->setY(usableArea.y());
|
||||
xit->setHeight(xit->height() - usableArea.y());
|
||||
}
|
||||
if (xit->x() + xit->width() > usableArea.width())
|
||||
xit->setWidth(usableArea.width() - xit->x());
|
||||
if (xit->y() + xit->height() > usableArea.height())
|
||||
xit->setHeight(usableArea.height() - xit->y());
|
||||
}
|
||||
}
|
||||
#endif // XINERAMA
|
||||
*/
|
||||
if (!RECT_EQUAL(old_area, area[i])) {
|
||||
/* the area has changed, adjust all the maximized windows */
|
||||
GSList *it;
|
||||
for (it = client_list; it; it = it->next) {
|
||||
Client *c = it->data;
|
||||
if (i < screen_num_desktops) {
|
||||
if (c->desktop == i)
|
||||
client_remaximize(c);
|
||||
} else {
|
||||
/* the 'all desktops' size */
|
||||
if (c->desktop == DESKTOP_ALL)
|
||||
client_remaximize(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* don't set these for the 'all desktops' area */
|
||||
if (i < screen_num_desktops) {
|
||||
dims[(i * 4) + 0] = area[i].x;
|
||||
dims[(i * 4) + 1] = area[i].y;
|
||||
dims[(i * 4) + 2] = area[i].width;
|
||||
dims[(i * 4) + 3] = area[i].height;
|
||||
}
|
||||
}
|
||||
PROP_SET32A(ob_root, net_workarea, cardinal,
|
||||
dims, 4 * screen_num_desktops);
|
||||
g_free(dims);
|
||||
}
|
||||
|
||||
Rect *screen_area(guint desktop)
|
||||
{
|
||||
if (desktop >= screen_num_desktops) {
|
||||
if (desktop == DESKTOP_ALL)
|
||||
return &area[screen_num_desktops];
|
||||
return NULL;
|
||||
}
|
||||
return &area[desktop];
|
||||
}
|
||||
|
||||
Strut *screen_strut(guint desktop)
|
||||
{
|
||||
if (desktop >= screen_num_desktops) {
|
||||
if (desktop == DESKTOP_ALL)
|
||||
return &strut[screen_num_desktops];
|
||||
return NULL;
|
||||
}
|
||||
return &strut[desktop];
|
||||
}
|
66
c/screen.h
66
c/screen.h
|
@ -1,66 +0,0 @@
|
|||
#ifndef __screen_h
|
||||
#define __screen_h
|
||||
|
||||
#include "geom.h"
|
||||
|
||||
struct Client;
|
||||
|
||||
#define DESKTOP_ALL (0xffffffff)
|
||||
|
||||
/*! The number of available desktops */
|
||||
extern guint screen_num_desktops;
|
||||
/*! The current desktop */
|
||||
extern guint screen_desktop;
|
||||
/*! The size of the screen */
|
||||
extern Size screen_physical_size;
|
||||
/*! Are we in showing-desktop mode? */
|
||||
extern gboolean screen_showing_desktop;
|
||||
|
||||
typedef struct DesktopLayout {
|
||||
guint orientation;
|
||||
guint start_corner;
|
||||
guint rows;
|
||||
guint columns;
|
||||
} DesktopLayout;
|
||||
extern DesktopLayout screen_desktop_layout;
|
||||
|
||||
/*! An array of gchar*'s which are desktop names in UTF-8 format */
|
||||
extern GPtrArray *screen_desktop_names;
|
||||
|
||||
/*! Take over the screen, set the basic hints on it claming it as ours */
|
||||
gboolean screen_annex();
|
||||
|
||||
/*! Once the screen is ours, set up its initial state */
|
||||
void screen_startup();
|
||||
/*! Free resources */
|
||||
void screen_shutdown();
|
||||
|
||||
/*! Figure out the new size of the screen and adjust stuff for it */
|
||||
void screen_resize();
|
||||
|
||||
/*! Change the number of available desktops */
|
||||
void screen_set_num_desktops(guint num);
|
||||
/*! Change the current desktop */
|
||||
void screen_set_desktop(guint num);
|
||||
|
||||
/*! Shows and focuses the desktop and hides all the client windows, or
|
||||
returns to the normal state, showing client windows. */
|
||||
void screen_show_desktop(gboolean show);
|
||||
|
||||
/*! Updates the desktop layout from the root property if available */
|
||||
void screen_update_layout();
|
||||
|
||||
/*! Get desktop names from the root window property */
|
||||
void screen_update_desktop_names();
|
||||
|
||||
/*! Installs or uninstalls a colormap for a client. If client is NULL, then
|
||||
it handles the root colormap. */
|
||||
void screen_install_colormap(struct Client *client, gboolean install);
|
||||
|
||||
void screen_update_struts();
|
||||
|
||||
Rect *screen_area(guint desktop);
|
||||
|
||||
Strut *screen_strut(guint desktop);
|
||||
|
||||
#endif
|
433
c/screenwrap.c
433
c/screenwrap.c
|
@ -1,433 +0,0 @@
|
|||
#include "screenwrap.h"
|
||||
#include "openbox.h"
|
||||
#include "screen.h"
|
||||
#include "kbind.h"
|
||||
#include "mbind.h"
|
||||
|
||||
ScreenWrap *screenwrap_instance;
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Define the type 'ScreenWrap'
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#define IS_SWRAP(v) ((v)->ob_type == &ScreenWrapType)
|
||||
#define CHECK_SWRAP(self, funcname) { \
|
||||
if (!IS_SWRAP(self)) { \
|
||||
PyErr_SetString(PyExc_TypeError, \
|
||||
"descriptor '" funcname "' a 'Screen' object"); \
|
||||
return NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
staticforward PyTypeObject ScreenWrapType;
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Attribute methods
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
static PyObject *swrap_number(ScreenWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_SWRAP(self, "number");
|
||||
if (!PyArg_ParseTuple(args, ":number"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(ob_screen);
|
||||
}
|
||||
|
||||
static PyObject *swrap_rootWindow(ScreenWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_SWRAP(self, "rootWindow");
|
||||
if (!PyArg_ParseTuple(args, ":rootWindow"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(ob_root);
|
||||
}
|
||||
|
||||
static PyObject *swrap_state(ScreenWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_SWRAP(self, "state");
|
||||
if (!PyArg_ParseTuple(args, ":state"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(ob_state);
|
||||
}
|
||||
|
||||
static PyObject *swrap_numDesktops(ScreenWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_SWRAP(self, "numDesktops");
|
||||
if (!PyArg_ParseTuple(args, ":numDesktops"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(screen_num_desktops);
|
||||
}
|
||||
|
||||
static PyObject *swrap_desktop(ScreenWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_SWRAP(self, "desktop");
|
||||
if (!PyArg_ParseTuple(args, ":desktop"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(screen_desktop);
|
||||
}
|
||||
|
||||
static PyObject *swrap_physicalSize(ScreenWrap *self, PyObject *args)
|
||||
{
|
||||
PyObject *tuple;
|
||||
|
||||
CHECK_SWRAP(self, "physicalSize");
|
||||
if (!PyArg_ParseTuple(args, ":physicalSize"))
|
||||
return NULL;
|
||||
tuple = PyTuple_New(2);
|
||||
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(screen_physical_size.width));
|
||||
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(screen_physical_size.height));
|
||||
return tuple;
|
||||
}
|
||||
|
||||
static PyObject *swrap_showingDesktop(ScreenWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_SWRAP(self, "showingDesktop");
|
||||
if (!PyArg_ParseTuple(args, ":showingDesktop"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(screen_showing_desktop ? 1 : 0);
|
||||
}
|
||||
|
||||
static PyObject *swrap_desktopLayout(ScreenWrap *self, PyObject *args)
|
||||
{
|
||||
PyObject *tuple;
|
||||
|
||||
CHECK_SWRAP(self, "desktopLayout");
|
||||
if (!PyArg_ParseTuple(args, ":desktopLayout"))
|
||||
return NULL;
|
||||
tuple = PyTuple_New(4);
|
||||
PyTuple_SET_ITEM(tuple, 0,
|
||||
PyInt_FromLong(screen_desktop_layout.orientation));
|
||||
PyTuple_SET_ITEM(tuple, 1,
|
||||
PyInt_FromLong(screen_desktop_layout.start_corner));
|
||||
PyTuple_SET_ITEM(tuple, 2,
|
||||
PyInt_FromLong(screen_desktop_layout.rows));
|
||||
PyTuple_SET_ITEM(tuple, 3,
|
||||
PyInt_FromLong(screen_desktop_layout.columns));
|
||||
return tuple;
|
||||
}
|
||||
|
||||
static PyObject *swrap_desktopNames(ScreenWrap *self, PyObject *args)
|
||||
{
|
||||
PyObject *list;
|
||||
guint s, i;
|
||||
|
||||
CHECK_SWRAP(self, "desktopNames");
|
||||
if (!PyArg_ParseTuple(args, ":desktopNames"))
|
||||
return NULL;
|
||||
s = screen_desktop_names->len;
|
||||
list = PyList_New(s);
|
||||
for (i = 0; i < s; ++i)
|
||||
PyList_SET_ITEM(list, i, PyString_FromString
|
||||
(g_ptr_array_index(screen_desktop_names, i)));
|
||||
return list;
|
||||
}
|
||||
|
||||
static PyObject *swrap_area(ScreenWrap *self, PyObject *args)
|
||||
{
|
||||
PyObject * tuple;
|
||||
Rect *r;
|
||||
guint i;
|
||||
|
||||
CHECK_SWRAP(self, "area");
|
||||
if (!PyArg_ParseTuple(args, "i:area", &i))
|
||||
return NULL;
|
||||
r = screen_area(i);
|
||||
if (r == NULL) {
|
||||
PyErr_SetString(PyExc_IndexError,
|
||||
"the requested desktop was not valid");
|
||||
return NULL;
|
||||
}
|
||||
tuple = PyTuple_New(4);
|
||||
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(r->x));
|
||||
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(r->y));
|
||||
PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(r->width));
|
||||
PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(r->height));
|
||||
return tuple;
|
||||
}
|
||||
|
||||
static PyObject *swrap_strut(ScreenWrap *self, PyObject *args)
|
||||
{
|
||||
PyObject *tuple;
|
||||
Strut *s;
|
||||
guint i;
|
||||
|
||||
CHECK_SWRAP(self, "strut");
|
||||
if (!PyArg_ParseTuple(args, "i:strut", &i))
|
||||
return NULL;
|
||||
s = screen_strut(i);
|
||||
if (s == NULL) {
|
||||
PyErr_SetString(PyExc_IndexError,
|
||||
"the requested desktop was not valid");
|
||||
return NULL;
|
||||
}
|
||||
tuple = PyTuple_New(4);
|
||||
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(s->left));
|
||||
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(s->top));
|
||||
PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(s->right));
|
||||
PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(s->bottom));
|
||||
return tuple;
|
||||
}
|
||||
|
||||
static PyObject *swrap_grabKey(ScreenWrap *self, PyObject *args)
|
||||
{
|
||||
PyObject *item, *tuple;
|
||||
GList *keylist = NULL, *it;
|
||||
int i, s;
|
||||
gboolean grab = FALSE;
|
||||
|
||||
CHECK_SWRAP(self, "grabKey");
|
||||
if (!PyArg_ParseTuple(args, "O:grabKey", &tuple))
|
||||
return NULL;
|
||||
|
||||
if (PyTuple_Check(tuple)) {
|
||||
s = PyTuple_GET_SIZE(tuple);
|
||||
if (s > 0) {
|
||||
for (i = 0; i < s; ++i) {
|
||||
item = PyTuple_GET_ITEM(tuple, i);
|
||||
if (!PyString_Check(item))
|
||||
break;
|
||||
keylist = g_list_append(keylist,
|
||||
g_strdup(PyString_AsString(item)));
|
||||
}
|
||||
if (i == s)
|
||||
grab = kbind_add(keylist);
|
||||
|
||||
for (it = keylist; it != NULL; it = it->next)
|
||||
g_free(it->data);
|
||||
g_list_free(it);
|
||||
|
||||
if (grab) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
} else {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"the key could not be grabbed");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "expected a tuple of strings");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject *swrap_clearKeyGrabs(ScreenWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_SWRAP(self, "clearKeyGrabs");
|
||||
if (!PyArg_ParseTuple(args, ":clearKeyGrabs"))
|
||||
return NULL;
|
||||
kbind_clearall();
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *swrap_grabKeyboard(ScreenWrap *self, PyObject *args)
|
||||
{
|
||||
int grab;
|
||||
|
||||
CHECK_SWRAP(self, "grabKeyboard");
|
||||
if (!PyArg_ParseTuple(args, "i:grabKeyboard", &grab))
|
||||
return NULL;
|
||||
if (!kbind_grab_keyboard(grab)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "failed to grab keyboard");
|
||||
return NULL;
|
||||
}
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *swrap_grabButton(ScreenWrap *self, PyObject *args)
|
||||
{
|
||||
char *name;
|
||||
char *context_str;
|
||||
GQuark context;
|
||||
|
||||
CHECK_SWRAP(self, "grabButton");
|
||||
if (!PyArg_ParseTuple(args, "ss:grabKey", &name, &context_str))
|
||||
return NULL;
|
||||
|
||||
context = g_quark_try_string(context_str);
|
||||
|
||||
if (!context) {
|
||||
PyErr_SetString(PyExc_ValueError, "invalid context");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mbind_add(name, context)) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
} else {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"the button could not be grabbed");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *swrap_clearButtonGrabs(ScreenWrap *self, PyObject *args)
|
||||
{
|
||||
CHECK_SWRAP(self, "clearButtonGrabs");
|
||||
if (!PyArg_ParseTuple(args, ":clearButtonGrabs"))
|
||||
return NULL;
|
||||
mbind_clearall();
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *swrap_grabPointer(ScreenWrap *self, PyObject *args)
|
||||
{
|
||||
int grab;
|
||||
|
||||
CHECK_SWRAP(self, "grabPointer");
|
||||
if (!PyArg_ParseTuple(args, "i:grabPointer", &grab))
|
||||
return NULL;
|
||||
if (!mbind_grab_pointer(grab)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "failed to grab pointer");
|
||||
return NULL;
|
||||
}
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyMethodDef ScreenWrapAttributeMethods[] = {
|
||||
{"number", (PyCFunction)swrap_number, METH_VARARGS,
|
||||
"Screen.number() -- Returns the number of the screen on the X server on "
|
||||
"which this Openbox instance is running."},
|
||||
{"rootWindow", (PyCFunction)swrap_rootWindow, METH_VARARGS,
|
||||
"Screen.rootWindow() -- Returns the window id of the root window."},
|
||||
{"state", (PyCFunction)swrap_state, METH_VARARGS,
|
||||
"Screen.state() -- Returns the running state of Openbox. One of the "
|
||||
"ob.State_ constants."},
|
||||
{"numDesktops", (PyCFunction)swrap_numDesktops, METH_VARARGS,
|
||||
"Screen.numDesktops() -- Returns the number of desktops available."},
|
||||
{"desktop", (PyCFunction)swrap_desktop, METH_VARARGS,
|
||||
"Screen.desktop() -- Returns the currently visible desktop."},
|
||||
{"physicalSize", (PyCFunction)swrap_physicalSize, METH_VARARGS,
|
||||
"Screen.physicalSize() -- Returns the physical size (in pixels) of the "
|
||||
"display in a tuple. The tuple is formatted as (width, height)."},
|
||||
{"showingDesktop", (PyCFunction)swrap_showingDesktop, METH_VARARGS,
|
||||
"Screen.showingDesktop() -- Returns if in showing-the-desktop mode or "
|
||||
"not."},
|
||||
{"desktopNames", (PyCFunction)swrap_desktopNames, METH_VARARGS,
|
||||
"Screen.desktopNames() -- Returns a list of the names of all the "
|
||||
"desktops, and possibly for desktops beyond those. The names are encoded "
|
||||
"as UTF-8."},
|
||||
{"desktopLayout", (PyCFunction)swrap_desktopLayout, METH_VARARGS,
|
||||
"Screen.desktopLayout() -- Returns the layout of the desktops, as "
|
||||
"specified by a compliant pager, in a tuple. The format of the tuple is "
|
||||
"(orientation, corner, rows, columns). Where, orientation is one of the "
|
||||
"ob.Orientation_ constants, corner is one of the ob.Corner_ constants, "
|
||||
"and rows and columns specify the size of the layout. The rows and "
|
||||
"columns will always include all the desktops."},
|
||||
{"area", (PyCFunction)swrap_area, METH_VARARGS,
|
||||
"Screen.area(d) -- Returns the usuable area on the Screen for a desktop, "
|
||||
"in the form of a tuple. The tuples format is (x, y, width, height). The "
|
||||
"desktop must be in the range of desktops on the screen, or 0xffffffff "
|
||||
"to get a combined area for 'all desktops'."},
|
||||
{"strut", (PyCFunction)swrap_area, METH_VARARGS,
|
||||
"Screen.strut(d) -- Returns the combined strut of all clients on a "
|
||||
"desktop, in the form of a tuple. The tuples format is "
|
||||
"(left, top, right, bottom). The desktop must be in the range of "
|
||||
"desktops on the screen, or 0xffffffff to get a combined strut for "
|
||||
"'all desktops'."},
|
||||
{"grabKey", (PyCFunction)swrap_grabKey, METH_VARARGS,
|
||||
"Screen.grabKey(('Mod1-C-a', 'd')) -- Grabs a key chain so that key "
|
||||
"events for it will occur. The argument must be a tuple of one or "
|
||||
"more elements. Each key element is made up of "
|
||||
"Modifier-Modifier-...-Key, where Modifier is one of Mod1, Mod2, "
|
||||
"Mod3, Mod4, Mod5, S (for Shift), or C (for Control)."},
|
||||
{"clearKeyGrabs", (PyCFunction)swrap_clearKeyGrabs, METH_VARARGS,
|
||||
"Screen.clearKeyGrabs() -- Removes all key grabs that have been done "
|
||||
"with grabKey()."},
|
||||
{"grabKeyboard", (PyCFunction)swrap_grabKeyboard, METH_VARARGS,
|
||||
"Screen.grabKeyboard(grab) -- Grabs or ungrabs the entire keyboard. When "
|
||||
"the keyboard is grabbed, all key presses will be sent to the "
|
||||
"hooks.keyboard hook. (grabbed keys will go to the hooks.events hook "
|
||||
"too. "},
|
||||
{"grabButton", (PyCFunction)swrap_grabButton, METH_VARARGS,
|
||||
"Screen.grabButton('C-1', \"frame\") -- Grabs a pointer button "
|
||||
"for the given context. The context must be one of the ob.Context_* "
|
||||
"constants. The button definition is made up of "
|
||||
"Modifier-Modifier-...-Button, where Modifier is one of Mod1, Mod2, "
|
||||
"Mod3, Mod4, Mod5, S (for Shift), or C (for Control)."},
|
||||
{"clearButtonGrabs", (PyCFunction)swrap_clearButtonGrabs, METH_VARARGS,
|
||||
"Screen.clearButtonGrabs() -- Removes all button grabs that have been "
|
||||
"done with grabButton()."},
|
||||
{"grabPointer", (PyCFunction)swrap_grabPointer, METH_VARARGS,
|
||||
"grabPointer(grab) -- Grabs or ungrabs the pointer device. When the "
|
||||
"pointer is grabbed, all pointer events will be sent to the "
|
||||
"hooks.pointer hook. (grabbed buttons will NOT go to the hooks.events "
|
||||
"hook while the pointer is grabbed)."},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Type methods/struct
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
static PyObject *swrap_getattr(ScreenWrap *self, char *name)
|
||||
{
|
||||
CHECK_SWRAP(self, "getattr");
|
||||
return Py_FindMethod(ScreenWrapAttributeMethods, (PyObject*)self, name);
|
||||
}
|
||||
|
||||
static void swrap_dealloc(ScreenWrap *self)
|
||||
{
|
||||
PyObject_Del((PyObject*) self);
|
||||
}
|
||||
|
||||
static PyTypeObject ScreenWrapType = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0,
|
||||
"Screen",
|
||||
sizeof(ScreenWrap),
|
||||
0,
|
||||
(destructor) swrap_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
(getattrfunc) swrap_getattr, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /*tp_hash */
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
External methods
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
void screenwrap_startup()
|
||||
{
|
||||
PyObject *ob, *obdict;
|
||||
ScreenWrap *swrap;
|
||||
|
||||
ScreenWrapType.ob_type = &PyType_Type;
|
||||
ScreenWrapType.tp_doc = "Wraps information and functionality global to an "
|
||||
"instance of Openbox.";
|
||||
PyType_Ready(&ScreenWrapType);
|
||||
swrap = PyObject_New(ScreenWrap, &ScreenWrapType);
|
||||
|
||||
/* get the ob module/dict */
|
||||
ob = PyImport_ImportModule("ob"); /* new */
|
||||
g_assert(ob != NULL);
|
||||
obdict = PyModule_GetDict(ob); /* borrowed */
|
||||
g_assert(obdict != NULL);
|
||||
|
||||
PyDict_SetItemString(obdict, "Screen", (PyObject*)swrap);
|
||||
Py_DECREF(swrap);
|
||||
Py_DECREF(ob);
|
||||
}
|
||||
|
||||
void screenwrap_shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
#ifndef __screenwrap_h
|
||||
#define __screenwrap_h
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
/* ScreenWrap is a PyObject */
|
||||
typedef struct ScreenWrap {
|
||||
PyObject_HEAD
|
||||
} ScreenWrap;
|
||||
|
||||
void screenwrap_startup();
|
||||
void screenwrap_shutdown();
|
||||
|
||||
#endif
|
116
c/stacking.c
116
c/stacking.c
|
@ -1,116 +0,0 @@
|
|||
#include "openbox.h"
|
||||
#include "prop.h"
|
||||
#include "focus.h"
|
||||
#include "client.h"
|
||||
#include "frame.h"
|
||||
#include <glib.h>
|
||||
|
||||
GList *stacking_list = NULL;
|
||||
|
||||
void stacking_set_list()
|
||||
{
|
||||
Window *windows, *win_it;
|
||||
GList *it;
|
||||
guint size = g_list_length(stacking_list);
|
||||
|
||||
/* create an array of the window ids (from bottom to top,
|
||||
reverse order!) */
|
||||
if (size > 0) {
|
||||
windows = g_new(Window, size);
|
||||
win_it = windows;
|
||||
for (it = g_list_last(stacking_list); it; it = it->prev, ++win_it)
|
||||
*win_it = ((Client*)it->data)->window;
|
||||
} else
|
||||
windows = NULL;
|
||||
|
||||
PROP_SET32A(ob_root, net_client_list_stacking, window, windows, size);
|
||||
|
||||
if (windows)
|
||||
g_free(windows);
|
||||
}
|
||||
|
||||
void stacking_raise(Client *client)
|
||||
{
|
||||
Window wins[2]; /* only ever restack 2 windows. */
|
||||
GList *it;
|
||||
Client *m;
|
||||
|
||||
g_assert(stacking_list != NULL); /* this would be bad */
|
||||
|
||||
m = client_find_modal_child(client);
|
||||
/* if we have a modal child, raise it instead, we'll go along tho later */
|
||||
if (m) stacking_raise(m);
|
||||
|
||||
/* remove the client before looking so we can't run into ourselves */
|
||||
stacking_list = g_list_remove(stacking_list, client);
|
||||
|
||||
/* the stacking list is from highest to lowest */
|
||||
it = stacking_list;
|
||||
while (it) {
|
||||
Client *c = it->data;
|
||||
if (client->layer >= c->layer && m != c)
|
||||
break;
|
||||
it = it->next;
|
||||
}
|
||||
|
||||
/*
|
||||
if our new position is the top, we want to stack under the focus_backup.
|
||||
otherwise, we want to stack under the previous window in the stack.
|
||||
*/
|
||||
if (it == stacking_list)
|
||||
wins[0] = focus_backup;
|
||||
else if (it != NULL)
|
||||
wins[0] = ((Client*)it->prev->data)->frame->window;
|
||||
else
|
||||
wins[0] = ((Client*)g_list_last(stacking_list)->data)->frame->window;
|
||||
wins[1] = client->frame->window;
|
||||
|
||||
stacking_list = g_list_insert_before(stacking_list, it, client);
|
||||
|
||||
XRestackWindows(ob_display, wins, 2);
|
||||
|
||||
stacking_set_list();
|
||||
}
|
||||
|
||||
void stacking_lower(Client *client)
|
||||
{
|
||||
Window wins[2]; /* only ever restack 2 windows. */
|
||||
GList *it;
|
||||
|
||||
g_assert(stacking_list != NULL); /* this would be bad */
|
||||
|
||||
it = g_list_last(stacking_list);
|
||||
|
||||
if (client->modal && client->transient_for) {
|
||||
/* don't let a modal window lower below its transient_for */
|
||||
it = g_list_find(stacking_list, client->transient_for);
|
||||
g_assert(it != NULL);
|
||||
|
||||
wins[0] = (it == stacking_list ? focus_backup :
|
||||
((Client*)it->prev->data)->frame->window);
|
||||
wins[1] = client->frame->window;
|
||||
if (wins[0] == wins[1]) return; /* already right above the window */
|
||||
|
||||
stacking_list = g_list_remove(stacking_list, client);
|
||||
stacking_list = g_list_insert_before(stacking_list, it, client);
|
||||
} else {
|
||||
while (it != stacking_list) {
|
||||
Client *c = it->data;
|
||||
if (client->layer >= c->layer)
|
||||
break;
|
||||
it = it->prev;
|
||||
}
|
||||
if (it->data == client) return; /* already the bottom, return */
|
||||
|
||||
wins[0] = ((Client*)it->data)->frame->window;
|
||||
wins[1] = client->frame->window;
|
||||
|
||||
stacking_list = g_list_remove(stacking_list, client);
|
||||
stacking_list = g_list_insert_before(stacking_list,
|
||||
it->next, client);
|
||||
}
|
||||
|
||||
XRestackWindows(ob_display, wins, 2);
|
||||
stacking_set_list();
|
||||
}
|
||||
|
26
c/stacking.h
26
c/stacking.h
|
@ -1,26 +0,0 @@
|
|||
#ifndef __stacking_h
|
||||
#define __stacking_h
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
struct Client;
|
||||
|
||||
extern GList *stacking_list;
|
||||
|
||||
/*! Sets the client stacking list on the root window from the
|
||||
stacking_clientlist */
|
||||
void stacking_set_list();
|
||||
|
||||
/*! Raises a client window above all others in its stacking layer
|
||||
raiseWindow has a couple of constraints that lowerWindow does not.<br>
|
||||
1) raiseWindow can be called after changing a Client's stack layer, and
|
||||
the list will be reorganized properly.<br>
|
||||
2) raiseWindow guarantees that XRestackWindows() will <i>always</i> be
|
||||
called for the specified client.
|
||||
*/
|
||||
void stacking_raise(struct Client *client);
|
||||
|
||||
/*! Lowers a client window below all others in its stacking layer */
|
||||
void stacking_lower(struct Client *client);
|
||||
|
||||
#endif
|
32
c/xerror.c
32
c/xerror.c
|
@ -1,32 +0,0 @@
|
|||
#include "openbox.h"
|
||||
#include <glib.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
static gboolean xerror_ignore = FALSE;
|
||||
|
||||
int xerror_handler(Display *d, XErrorEvent *e)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (!xerror_ignore) {
|
||||
char errtxt[128];
|
||||
|
||||
/*if (e->error_code != BadWindow) */
|
||||
{
|
||||
XGetErrorText(d, e->error_code, errtxt, 127);
|
||||
if (e->error_code == BadWindow)
|
||||
g_warning("X Error: %s", errtxt);
|
||||
else
|
||||
g_error("X Error: %s", errtxt);
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)d; (void)e;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void xerror_set_ignore(gboolean ignore)
|
||||
{
|
||||
XSync(ob_display, FALSE);
|
||||
xerror_ignore = ignore;
|
||||
}
|
11
c/xerror.h
11
c/xerror.h
|
@ -1,11 +0,0 @@
|
|||
#ifndef __xerror_h
|
||||
#define __xerror_h
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <glib.h>
|
||||
|
||||
int xerror_handler(Display *, XErrorEvent *);
|
||||
|
||||
void xerror_set_ignore(gboolean ignore);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue