diff options
author | fluxgen <fluxgen> | 2003-04-15 14:40:24 (GMT) |
---|---|---|
committer | fluxgen <fluxgen> | 2003-04-15 14:40:24 (GMT) |
commit | 9e96f89dbe6ad5a8ace36128d50d1c6737968fa8 (patch) | |
tree | d4e3420d3e070bd06667af40b2aa7e6e2ea9b312 /src | |
parent | 86f3dc3b8cb7bb1130343456b35db05c8ac0f4a0 (diff) | |
download | fluxbox-9e96f89dbe6ad5a8ace36128d50d1c6737968fa8.zip fluxbox-9e96f89dbe6ad5a8ace36128d50d1c6737968fa8.tar.bz2 |
drag and drop support for tabs
Diffstat (limited to 'src')
-rw-r--r-- | src/Window.cc | 127 | ||||
-rw-r--r-- | src/Window.hh | 7 |
2 files changed, 123 insertions, 11 deletions
diff --git a/src/Window.cc b/src/Window.cc index e207af3..ec82bd5 100644 --- a/src/Window.cc +++ b/src/Window.cc | |||
@@ -22,7 +22,7 @@ | |||
22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
23 | // DEALINGS IN THE SOFTWARE. | 23 | // DEALINGS IN THE SOFTWARE. |
24 | 24 | ||
25 | // $Id: Window.cc,v 1.134 2003/04/15 12:31:53 fluxgen Exp $ | 25 | // $Id: Window.cc,v 1.135 2003/04/15 14:40:24 fluxgen Exp $ |
26 | 26 | ||
27 | #include "Window.hh" | 27 | #include "Window.hh" |
28 | 28 | ||
@@ -238,7 +238,7 @@ FluxboxWindow::~FluxboxWindow() { | |||
238 | #ifdef DEBUG | 238 | #ifdef DEBUG |
239 | cerr<<__FILE__<<"("<<__LINE__<<"): starting ~FluxboxWindow("<<this<<")"<<endl; | 239 | cerr<<__FILE__<<"("<<__LINE__<<"): starting ~FluxboxWindow("<<this<<")"<<endl; |
240 | #endif // DEBUG | 240 | #endif // DEBUG |
241 | if (moving || resizing) { | 241 | if (moving || resizing || m_attaching_tab) { |
242 | screen.hideGeometry(); | 242 | screen.hideGeometry(); |
243 | XUngrabPointer(display, CurrentTime); | 243 | XUngrabPointer(display, CurrentTime); |
244 | } | 244 | } |
@@ -266,21 +266,24 @@ FluxboxWindow::~FluxboxWindow() { | |||
266 | detachClient(*m_clientlist.back()); | 266 | detachClient(*m_clientlist.back()); |
267 | } | 267 | } |
268 | } | 268 | } |
269 | 269 | Fluxbox::instance()->removeWindowSearch(m_frame.window().window()); | |
270 | #ifdef DEBUG | 270 | #ifdef DEBUG |
271 | cerr<<__FILE__<<"("<<__LINE__<<"): ~FluxboxWindow("<<this<<")"<<endl; | 271 | cerr<<__FILE__<<"("<<__LINE__<<"): ~FluxboxWindow("<<this<<")"<<endl; |
272 | #endif // DEBUG | 272 | #endif // DEBUG |
273 | } | 273 | } |
274 | 274 | ||
275 | 275 | ||
276 | void FluxboxWindow::init() { | 276 | void FluxboxWindow::init() { |
277 | m_attaching_tab = 0; | ||
277 | assert(m_client); | 278 | assert(m_client); |
278 | //!! TODO init of client should be better | 279 | //!! TODO init of client should be better |
279 | // we don't want to duplicate code here and in attachClient | 280 | // we don't want to duplicate code here and in attachClient |
280 | m_clientlist.push_back(m_client); | 281 | m_clientlist.push_back(m_client); |
281 | #ifdef DEBUG | 282 | #ifdef DEBUG |
282 | cerr<<__FILE__<<": FluxboxWindow::init(this="<<this<<", client="<<hex<<m_client->window()<<dec<<")"<<endl; | 283 | cerr<<__FILE__<<": FluxboxWindow::init(this="<<this<<", client="<<hex<< |
283 | #endif // DEBUG | 284 | m_client->window()<<", frame = "<<m_frame.window().window()<<dec<<")"<<endl; |
285 | |||
286 | #endif // DEBUG | ||
284 | TextButton *btn = new TextButton(m_frame.label(), | 287 | TextButton *btn = new TextButton(m_frame.label(), |
285 | m_frame.theme().font(), | 288 | m_frame.theme().font(), |
286 | m_client->title()); | 289 | m_client->title()); |
@@ -361,6 +364,8 @@ void FluxboxWindow::init() { | |||
361 | 364 | ||
362 | Fluxbox *fluxbox = Fluxbox::instance(); | 365 | Fluxbox *fluxbox = Fluxbox::instance(); |
363 | 366 | ||
367 | fluxbox->saveWindowSearch(m_frame.window().window(), this); | ||
368 | |||
364 | timer.setTimeout(fluxbox->getAutoRaiseDelay()); | 369 | timer.setTimeout(fluxbox->getAutoRaiseDelay()); |
365 | timer.fireOnce(true); | 370 | timer.fireOnce(true); |
366 | 371 | ||
@@ -2187,15 +2192,17 @@ void FluxboxWindow::shapeEvent(XShapeEvent *) { } | |||
2187 | 2192 | ||
2188 | void FluxboxWindow::buttonReleaseEvent(XButtonEvent &re) { | 2193 | void FluxboxWindow::buttonReleaseEvent(XButtonEvent &re) { |
2189 | 2194 | ||
2190 | |||
2191 | if (isMoving()) | 2195 | if (isMoving()) |
2192 | stopMoving(); | 2196 | stopMoving(); |
2193 | else if (isResizing()) | 2197 | else if (isResizing()) |
2194 | stopResizing(); | 2198 | stopResizing(); |
2199 | else if (m_attaching_tab) | ||
2200 | attachTo(re.x_root, re.y_root); | ||
2195 | else if (re.window == m_frame.window()) { | 2201 | else if (re.window == m_frame.window()) { |
2196 | if (re.button == 2 && re.state == Mod1Mask) | 2202 | if (re.button == 2 && re.state == Mod1Mask) |
2197 | XUngrabPointer(display, CurrentTime); | 2203 | XUngrabPointer(display, CurrentTime); |
2198 | m_frame.buttonReleaseEvent(re); | 2204 | else |
2205 | m_frame.buttonReleaseEvent(re); | ||
2199 | } else { | 2206 | } else { |
2200 | m_frame.buttonReleaseEvent(re); | 2207 | m_frame.buttonReleaseEvent(re); |
2201 | } | 2208 | } |
@@ -2208,7 +2215,7 @@ void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) { | |||
2208 | } | 2215 | } |
2209 | bool inside_titlebar = (m_frame.titlebar() == me.window || m_frame.label() == me.window || | 2216 | bool inside_titlebar = (m_frame.titlebar() == me.window || m_frame.label() == me.window || |
2210 | m_frame.handle() == me.window || m_frame.window() == me.window); | 2217 | m_frame.handle() == me.window || m_frame.window() == me.window); |
2211 | 2218 | WinClient *client = 0; | |
2212 | if (!inside_titlebar) { | 2219 | if (!inside_titlebar) { |
2213 | // determine if we're in titlebar | 2220 | // determine if we're in titlebar |
2214 | Client2ButtonMap::iterator it = m_labelbuttons.begin(); | 2221 | Client2ButtonMap::iterator it = m_labelbuttons.begin(); |
@@ -2216,6 +2223,7 @@ void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) { | |||
2216 | for (; it != it_end; ++it) { | 2223 | for (; it != it_end; ++it) { |
2217 | if ((*it).second->window() == me.window) { | 2224 | if ((*it).second->window() == me.window) { |
2218 | inside_titlebar = true; | 2225 | inside_titlebar = true; |
2226 | client = (*it).first; | ||
2219 | break; | 2227 | break; |
2220 | } | 2228 | } |
2221 | } | 2229 | } |
@@ -2337,6 +2345,74 @@ void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) { | |||
2337 | if (screen.doShowWindowPos()) | 2345 | if (screen.doShowWindowPos()) |
2338 | screen.showGeometry(gx, gy); | 2346 | screen.showGeometry(gx, gy); |
2339 | } | 2347 | } |
2348 | } else if ((me.state & Button2Mask) && inside_titlebar && client != 0) { | ||
2349 | |||
2350 | // | ||
2351 | // drag'n'drop code for tabs | ||
2352 | // | ||
2353 | if (m_attaching_tab == 0) { | ||
2354 | cerr<<"starting m_attching_tab for this="<<this<<endl; | ||
2355 | // start drag'n'drop for tab | ||
2356 | m_attaching_tab = client; | ||
2357 | |||
2358 | XGrabPointer(display, me.window, False, Button2MotionMask | | ||
2359 | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, | ||
2360 | None, Fluxbox::instance()->getMoveCursor(), CurrentTime); | ||
2361 | last_move_x = me.x_root - 1; | ||
2362 | last_move_y = me.y_root - 1; | ||
2363 | |||
2364 | XDrawRectangle(display, getScreen().getRootWindow(), | ||
2365 | getScreen().getOpGC(), | ||
2366 | last_move_x, last_move_y, | ||
2367 | m_labelbuttons[client]->width(), | ||
2368 | m_labelbuttons[client]->height()); | ||
2369 | } else { | ||
2370 | // we already grabed and started to drag'n'drop tab | ||
2371 | // so we update drag'n'drop-rectangle | ||
2372 | int dx = me.x_root - 1, dy = me.y_root - 1; | ||
2373 | |||
2374 | dx -= getScreen().getBorderWidth(); | ||
2375 | dy -= getScreen().getBorderWidth(); | ||
2376 | |||
2377 | if (getScreen().getEdgeSnapThreshold()) { | ||
2378 | int drx = getScreen().getWidth() - (dx + 1); | ||
2379 | |||
2380 | if (dx > 0 && dx < drx && dx < getScreen().getEdgeSnapThreshold()) | ||
2381 | dx = 0; | ||
2382 | else if (drx > 0 && drx < getScreen().getEdgeSnapThreshold()) | ||
2383 | dx = getScreen().getWidth() - 1; | ||
2384 | |||
2385 | int dty, dby; | ||
2386 | |||
2387 | dty = dy; | ||
2388 | dby = -dy - 1; | ||
2389 | |||
2390 | if (dy > 0 && dty < getScreen().getEdgeSnapThreshold()) | ||
2391 | dy = 0; | ||
2392 | else if (dby > 0 && dby < getScreen().getEdgeSnapThreshold()) | ||
2393 | dy = - 1; | ||
2394 | |||
2395 | } | ||
2396 | |||
2397 | //erase rectangle | ||
2398 | XDrawRectangle(display, getScreen().getRootWindow(), | ||
2399 | getScreen().getOpGC(), | ||
2400 | last_move_x, last_move_y, | ||
2401 | m_labelbuttons[client]->width(), | ||
2402 | m_labelbuttons[client]->height()); | ||
2403 | |||
2404 | |||
2405 | //redraw rectangle at new pos | ||
2406 | last_move_x = dx; | ||
2407 | last_move_y = dy; | ||
2408 | XDrawRectangle(display, getScreen().getRootWindow(), | ||
2409 | getScreen().getOpGC(), | ||
2410 | last_move_x, last_move_y, | ||
2411 | m_labelbuttons[client]->width(), | ||
2412 | m_labelbuttons[client]->height()); | ||
2413 | |||
2414 | |||
2415 | } | ||
2340 | } | 2416 | } |
2341 | 2417 | ||
2342 | } | 2418 | } |
@@ -2592,6 +2668,39 @@ void FluxboxWindow::stopResizing(Window win) { | |||
2592 | XUngrabPointer(display, CurrentTime); | 2668 | XUngrabPointer(display, CurrentTime); |
2593 | } | 2669 | } |
2594 | 2670 | ||
2671 | void FluxboxWindow::attachTo(int x, int y) { | ||
2672 | if (m_attaching_tab == 0) | ||
2673 | return; | ||
2674 | |||
2675 | XUngrabPointer(display, CurrentTime); | ||
2676 | |||
2677 | |||
2678 | XDrawRectangle(display, getScreen().getRootWindow(), | ||
2679 | getScreen().getOpGC(), | ||
2680 | last_move_x, last_move_y, | ||
2681 | m_labelbuttons[m_attaching_tab]->width(), | ||
2682 | m_labelbuttons[m_attaching_tab]->height()); | ||
2683 | |||
2684 | int dest_x = 0, dest_y = 0; | ||
2685 | Window child = 0; | ||
2686 | |||
2687 | if (XTranslateCoordinates(display, getScreen().getRootWindow(), | ||
2688 | getScreen().getRootWindow(), | ||
2689 | x, y, &dest_x, &dest_y, &child)) { | ||
2690 | // search for a fluxboxwindow | ||
2691 | FluxboxWindow *attach_to_win = Fluxbox::instance()->searchWindow(child); | ||
2692 | |||
2693 | if (attach_to_win != this && | ||
2694 | attach_to_win != 0) { | ||
2695 | attach_to_win->attachClient(*m_attaching_tab); | ||
2696 | } else if (attach_to_win != this) { // disconnect client if we didn't drop on a window | ||
2697 | detachClient(*m_attaching_tab); | ||
2698 | } | ||
2699 | |||
2700 | } | ||
2701 | m_attaching_tab = 0; | ||
2702 | } | ||
2703 | |||
2595 | //finds and redraw the icon label | 2704 | //finds and redraw the icon label |
2596 | void FluxboxWindow::updateIcon() { | 2705 | void FluxboxWindow::updateIcon() { |
2597 | if (Fluxbox::instance()->useIconBar()) { | 2706 | if (Fluxbox::instance()->useIconBar()) { |
diff --git a/src/Window.hh b/src/Window.hh index e8e4641..c246e9f 100644 --- a/src/Window.hh +++ b/src/Window.hh | |||
@@ -22,7 +22,7 @@ | |||
22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
23 | // DEALINGS IN THE SOFTWARE. | 23 | // DEALINGS IN THE SOFTWARE. |
24 | 24 | ||
25 | // $Id: Window.hh,v 1.54 2003/04/14 14:45:14 fluxgen Exp $ | 25 | // $Id: Window.hh,v 1.55 2003/04/15 14:39:15 fluxgen Exp $ |
26 | 26 | ||
27 | #ifndef WINDOW_HH | 27 | #ifndef WINDOW_HH |
28 | #define WINDOW_HH | 28 | #define WINDOW_HH |
@@ -318,7 +318,9 @@ private: | |||
318 | void startResizing(Window win, int x, int y, bool left); | 318 | void startResizing(Window win, int x, int y, bool left); |
319 | void stopResizing(Window win=0); | 319 | void stopResizing(Window win=0); |
320 | void updateIcon(); | 320 | void updateIcon(); |
321 | 321 | /// try to attach current attaching client to a window at pos x, y | |
322 | void attachTo(int x, int y); | ||
323 | |||
322 | void updateTransientInfo(); | 324 | void updateTransientInfo(); |
323 | 325 | ||
324 | bool getState(); | 326 | bool getState(); |
@@ -355,6 +357,7 @@ private: | |||
355 | //Window state | 357 | //Window state |
356 | bool moving, resizing, shaded, maximized, visible, iconic, transient, | 358 | bool moving, resizing, shaded, maximized, visible, iconic, transient, |
357 | focused, stuck, modal, send_focus_message, m_managed; | 359 | focused, stuck, modal, send_focus_message, m_managed; |
360 | WinClient *m_attaching_tab; | ||
358 | 361 | ||
359 | BScreen &screen; /// screen on which this window exist | 362 | BScreen &screen; /// screen on which this window exist |
360 | FbTk::Timer timer; | 363 | FbTk::Timer timer; |