global python scripts. client motion/resizing is all done via python now
[mikachu/openbox.git] / src / actions.cc
1 // -*- mode: C++; indent-tabs-mode: nil; -*-
2
3 #ifdef HAVE_CONFIG_H
4 # include "../config.h"
5 #endif
6
7 #include "actions.hh"
8 #include "widget.hh"
9 #include "openbox.hh"
10 #include "client.hh"
11 #include "python.hh"
12 #include "otk/display.hh"
13
14 #include <stdio.h>
15
16 namespace ob {
17
18 const unsigned int OBActions::DOUBLECLICKDELAY = 300;
19
20 OBActions::OBActions()
21   : _button(0)
22 {
23   // XXX: load a configuration out of somewhere
24
25 }
26
27
28 OBActions::~OBActions()
29 {
30 }
31
32
33 void OBActions::buttonPressHandler(const XButtonEvent &e)
34 {
35   OtkEventHandler::buttonPressHandler(e);
36   
37   // run the PRESS guile hook
38   OBWidget *w = dynamic_cast<OBWidget*>
39     (Openbox::instance->findHandler(e.window));
40
41   python_callback(Action_ButtonPress, e.window,
42                   (OBWidget::WidgetType)(w ? w->type():-1),
43                   e.state, e.button, e.x_root, e.y_root, e.time);
44     
45   if (_button) return; // won't count toward CLICK events
46
47   _button = e.button;
48 }
49   
50
51 void OBActions::buttonReleaseHandler(const XButtonEvent &e)
52 {
53   OtkEventHandler::buttonReleaseHandler(e);
54   
55   OBWidget *w = dynamic_cast<OBWidget*>
56     (Openbox::instance->findHandler(e.window));
57
58   // run the RELEASE guile hook
59   python_callback(Action_ButtonRelease, e.window,
60                   (OBWidget::WidgetType)(w ? w->type():-1),
61                   e.state, e.button, e.x_root, e.y_root, e.time);
62
63   // not for the button we're watching?
64   if (_button != e.button) return;
65
66   _button = 0;
67
68   // find the area of the window
69   XWindowAttributes attr;
70   if (!XGetWindowAttributes(otk::OBDisplay::display, e.window, &attr)) return;
71
72   // if not on the window any more, it isnt a CLICK
73   if (!(e.same_screen && e.x >= 0 && e.y >= 0 &&
74         e.x < attr.width && e.y < attr.height))
75     return;
76
77   // run the CLICK guile hook
78   python_callback(Action_Click, e.window,
79                   (OBWidget::WidgetType)(w ? w->type():-1),
80                   e.state, e.button, e.time);
81
82   if (e.time - _release.time < DOUBLECLICKDELAY &&
83       _release.win == e.window && _release.button == e.button) {
84
85     // run the DOUBLECLICK guile hook
86     python_callback(Action_DoubleClick, e.window,
87                   (OBWidget::WidgetType)(w ? w->type():-1),
88                   e.state, e.button, e.time);
89
90     // reset so you cant triple click for 2 doubleclicks
91     _release.win = 0;
92     _release.button = 0;
93     _release.time = 0;
94   } else {
95     // save the button release, might be part of a double click
96     _release.win = e.window;
97     _release.button = e.button;
98     _release.time = e.time;
99   }
100 }
101
102
103 void OBActions::enterHandler(const XCrossingEvent &e)
104 {
105   OtkEventHandler::enterHandler(e);
106   
107   OBWidget *w = dynamic_cast<OBWidget*>
108     (Openbox::instance->findHandler(e.window));
109
110   // run the ENTER guile hook
111   python_callback(Action_EnterWindow, e.window,
112                   (OBWidget::WidgetType)(w ? w->type():-1), e.state);
113 }
114
115
116 void OBActions::leaveHandler(const XCrossingEvent &e)
117 {
118   OtkEventHandler::leaveHandler(e);
119
120   OBWidget *w = dynamic_cast<OBWidget*>
121     (Openbox::instance->findHandler(e.window));
122
123   // run the LEAVE guile hook
124   python_callback(Action_LeaveWindow, e.window,
125                   (OBWidget::WidgetType)(w ? w->type():-1), e.state);
126 }
127
128
129 void OBActions::keyPressHandler(const XKeyEvent &e)
130 {
131   OBWidget *w = dynamic_cast<OBWidget*>
132     (Openbox::instance->findHandler(e.window));
133
134   // run the KEY guile hook
135   python_callback(Action_KeyPress, e.window,
136                   (OBWidget::WidgetType)(w ? w->type():-1),
137                   e.state, e.keycode);
138 }
139
140
141 void OBActions::motionHandler(const XMotionEvent &e)
142 {
143   if (!e.same_screen) return; // this just gets stupid
144
145   int x_root = e.x_root, y_root = e.y_root;
146   
147   // compress changes to a window into a single change
148   XEvent ce;
149   while (XCheckTypedEvent(otk::OBDisplay::display, e.type, &ce)) {
150     if (ce.xmotion.window != e.window) {
151       XPutBackEvent(otk::OBDisplay::display, &ce);
152       break;
153     } else {
154       x_root = e.x_root;
155       y_root = e.y_root;
156     }
157   }
158
159
160   OBWidget *w = dynamic_cast<OBWidget*>
161     (Openbox::instance->findHandler(e.window));
162
163   // XXX: i can envision all sorts of crazy shit with this.. gestures, etc
164   //      maybe that should all be done via python tho..
165   // run the simple MOTION guile hook for now...
166   python_callback(Action_MouseMotion, e.window,
167                   (OBWidget::WidgetType)(w ? w->type():-1),
168                   e.state, e.x_root, e.y_root, e.time);
169 }
170
171
172 }