diff -ur matchbox-window-manager-1.2/src//client_common.c matchbox-window-manager-1.2-swipe/src//client_common.c --- matchbox-window-manager-1.2/src//client_common.c 2007-08-13 03:36:49.000000000 -0600 +++ matchbox-window-manager-1.2-swipe/src//client_common.c 2011-09-29 00:12:03.000000000 -0600 @@ -553,7 +553,7 @@ attr.override_redirect = True; attr.background_pixel = w->grey_col.pixel; - attr.event_mask = ButtonMask; + attr.event_mask = ButtonMask|ButtonMotionMask; if (height_north > 0) c->frames_decor[NORTH] = diff -ur matchbox-window-manager-1.2/src//wm.c matchbox-window-manager-1.2-swipe/src//wm.c --- matchbox-window-manager-1.2/src//wm.c 2007-10-12 04:58:51.000000000 -0600 +++ matchbox-window-manager-1.2-swipe/src//wm.c 2012-07-24 16:35:51.000000000 -0600 @@ -870,6 +870,105 @@ } #endif + +// BEGIN stack.c code +static void _stack_add_below_client(Client *client, Client *client_above){ + Wm *w = client->wm; + + if (client_above == NULL) + { + /* nothing above raising to top */ + if (w->stack_top) + { + client->below = w->stack_top; + w->stack_top->below = client; + } + + w->stack_top = client; + } + else + { + client->above = client_above; + client->below = client_above->below; + + if (client_above->below) client_above->below->above = client; + client_above->below = client; + } + + if (client_above == w->stack_bottom) + w->stack_bottom = client; + + w->stack_n_items++; +} +static void _stack_move_below_client(Client *client, Client *client_above){ + if (client == client_above) return; + + stack_remove(client); + _stack_add_below_client(client, client_above); + + /* must move any transients too */ +} +// END stack.c code +static int button_drag_start_x, button_drag_start_y; +static int base_window_x = 0, base_window_y = 0; +static int button_window_x = 0, button_window_y = 0; +static int base_titlebar_height = 0, base_window_width = 0; +static int button_init_left = 0, button_init_right = 0; +static Client *button_drag_client = NULL, *button_other_client = NULL; +static Client *_stack_get_below( Wm *w, int *desktop ){ + Client *cc; + for(cc = button_drag_client->below; cc != NULL; cc = cc->below){ + if(cc->type == MBCLIENT_TYPE_DESKTOP){ *desktop = 1; continue; } + if(cc->type == MBCLIENT_TYPE_APP && cc->mapped) return cc; + } + return NULL; +} +static void slide_window( Client *c, int x, int y ){ + XMoveWindow(c->wm->dpy, c->frame, x, y); + button_window_x = x; + button_window_y = y; +} +static void _slide_window( Client *c, int x, int y ){ + XMoveWindow(c->wm->dpy, c->frame, x, y); +} +static void slide_window_reset_left( Wm *w ){ + if(button_other_client == NULL) return; + _slide_window(button_other_client, base_window_x, base_window_y); + + Client *lowest = stack_get_lowest(w, MBCLIENT_TYPE_APP); + if(lowest != button_other_client){ + _stack_move_below_client(button_other_client, lowest); + + int desktop = 0; + Client *below = _stack_get_below(w, &desktop); + if(below) + _slide_window(below, base_window_x + base_window_width, base_window_y); // move off screen + wm_activate_client(stack_cycle_forward(w, MBCLIENT_TYPE_APP)); + wm_activate_client(stack_cycle_backward(w, MBCLIENT_TYPE_APP)); + if(below) + _slide_window(below, base_window_x, base_window_y); // move on screen + } +} +static void get_window_base( Wm *w, Client *c ){ + if(c == NULL) return; + + XWindowAttributes attr; + XGetWindowAttributes(c->wm->dpy, c->frame, &attr); + button_window_x = base_window_x = attr.x; + button_window_y = base_window_y = attr.y; + + base_window_width = c->width; + + XRectangle rect; + if(c->flags & CLIENT_FULLSCREEN_FLAG) + base_titlebar_height = 0; + else if(mbtheme_get_titlebar_panel_rect(w->mbtheme, &rect, c)) + base_titlebar_height = rect.height; + else + base_titlebar_height = 0; +} + + /* Main event loop, timeout for polling stuff */ void wm_event_loop(Wm* w) @@ -901,6 +1000,11 @@ if (get_xevent_timed(w, &ev, &tvt)) { + #define H_SWIPE_X_DEVIATION 50 + #define H_SWIPE_Y_DEVIATION 20 + #define V_SWIPE_X_DEVIATION 20 + #define V_SWIPE_Y_DEVIATION 50 + #define WINDOW_SLIDE_DELTA 10 switch (ev.type) { @@ -910,7 +1014,160 @@ break; #endif case ButtonPress: - wm_handle_button_event(w, &ev.xbutton); break; + button_drag_client = button_other_client = NULL; + button_drag_start_x = ev.xbutton.x; + button_drag_start_y = ev.xbutton.y; + wm_handle_button_event(w, &ev.xbutton); + get_window_base(w, button_drag_client); + button_init_left = button_init_right = 0; + break; + case MotionNotify: + if(button_drag_client){ + // slide window as finger moves + int offset_x = ev.xmotion.x - button_drag_start_x, offset_y = ev.xmotion.y - button_drag_start_y; + if(button_drag_client && button_drag_start_y < base_titlebar_height){ + if(button_window_x + ev.xmotion.x >= base_window_x + button_drag_start_x + H_SWIPE_X_DEVIATION && offset_y > -H_SWIPE_Y_DEVIATION && offset_y < H_SWIPE_Y_DEVIATION){ + // right swipe + + if(button_init_left){ + // reset + button_init_left = 0; + slide_window_reset_left(w); + } + + int desktop = 0; + button_other_client = _stack_get_below(w, &desktop); + if(desktop && button_other_client){ + // ensure window uncovered on left side is the window that will be switched to + _slide_window(button_other_client, base_window_x + base_window_width, base_window_y); // move off screen + wm_activate_client(stack_cycle_forward(w, MBCLIENT_TYPE_APP)); + wm_activate_client(stack_cycle_backward(w, MBCLIENT_TYPE_APP)); + _slide_window(button_other_client, base_window_x, base_window_y); // move on screen + } + button_init_right = 1; + + int x = (button_window_x + ev.xmotion.x) - (button_drag_start_x + H_SWIPE_X_DEVIATION); + if(x > button_window_x+WINDOW_SLIDE_DELTA || x < button_window_x-WINDOW_SLIDE_DELTA){ + slide_window(button_drag_client, x, base_window_y); + if(button_other_client) + _slide_window(button_other_client, x - base_window_width, base_window_y); + } + } else if(button_window_x + ev.xmotion.x <= base_window_x + button_drag_start_x - H_SWIPE_X_DEVIATION && offset_y > -H_SWIPE_Y_DEVIATION && offset_y < H_SWIPE_Y_DEVIATION){ + // left swipe + + if(button_init_right){ + // reset + button_init_right = 0; + if(button_other_client) + _slide_window(button_other_client, base_window_x, base_window_y); + } + + if(!button_init_left){ + // ensure window uncovered on right side is the window that will be switched to + button_other_client = stack_get_lowest(w, MBCLIENT_TYPE_APP); + if(button_other_client == button_drag_client) + button_other_client = NULL; + else if(button_other_client){ + _slide_window(button_other_client, base_window_x + base_window_width, base_window_y); // move off screen + wm_activate_client(button_other_client); + stack_move_above_client(button_drag_client, button_other_client); + wm_activate_client(stack_cycle_forward(w, MBCLIENT_TYPE_APP)); + wm_activate_client(stack_cycle_backward(w, MBCLIENT_TYPE_APP)); + } + button_init_left = 1; + } + + int x = (button_window_x + ev.xmotion.x) - (button_drag_start_x - H_SWIPE_X_DEVIATION); + if(x > button_window_x+WINDOW_SLIDE_DELTA || x < button_window_x-WINDOW_SLIDE_DELTA){ + slide_window(button_drag_client, x, base_window_y); + if(button_other_client) + _slide_window(button_other_client, x + base_window_width, base_window_y); + } + } else if(button_window_y + ev.xmotion.y >= base_titlebar_height && offset_x >= -V_SWIPE_X_DEVIATION && offset_x <= V_SWIPE_X_DEVIATION){ + // down swipe + + if(button_init_right){ + // reset + button_init_right = 0; + if(button_other_client) + _slide_window(button_other_client, base_window_x, base_window_y); + } else if(button_init_left){ + // reset + button_init_left = 0; + slide_window_reset_left(w); + } + + int desktop = 0; + button_other_client = _stack_get_below(w, &desktop); + if(desktop && button_other_client){ + // ensure window uncovered at top is the window that will be switched to + _slide_window(button_other_client, base_window_x + base_window_width, base_window_y); // move off screen + wm_activate_client(stack_cycle_forward(w, MBCLIENT_TYPE_APP)); + wm_activate_client(stack_cycle_backward(w, MBCLIENT_TYPE_APP)); + _slide_window(button_other_client, base_window_x, base_window_y); // move on screen + } + + int y = (button_window_y + ev.xmotion.y) - base_titlebar_height; + if(y > button_window_y+WINDOW_SLIDE_DELTA || y < button_window_y-WINDOW_SLIDE_DELTA) + slide_window(button_drag_client, base_window_x, y); + } else if((button_window_x || button_window_y) && (button_window_x != base_window_x || button_window_y != base_window_y)){ + // snap window back to base coordinates, if finger deviates from path + slide_window(button_drag_client, base_window_x, base_window_y); + if(button_init_right){ + button_init_right = 0; + if(button_other_client) + _slide_window(button_other_client, base_window_x, base_window_y); + } else if(button_init_left){ + button_init_left = 0; + slide_window_reset_left(w); + } + } + } + } + break; + case ButtonRelease: + if(button_drag_client){ + // snap window back to base coordinates + if(button_window_x || button_window_y){ + _slide_window(button_drag_client, base_window_x, base_window_y); + if(button_init_right && button_other_client) + _slide_window(button_other_client, base_window_x, base_window_y); + if(button_init_left) + slide_window_reset_left(w); + } + + // perform action + if(button_drag_start_y < base_titlebar_height){ + if(button_window_x + ev.xbutton.x > base_window_x + button_drag_start_x + H_SWIPE_X_DEVIATION + && (ev.xbutton.y > button_drag_start_y - H_SWIPE_Y_DEVIATION && ev.xbutton.y < button_drag_start_y + H_SWIPE_Y_DEVIATION) + ){ + // right swipe + wm_activate_client(stack_cycle_forward(w, MBCLIENT_TYPE_APP)); + } else if(button_window_x + ev.xbutton.x < base_window_x + button_drag_start_x - H_SWIPE_X_DEVIATION + && (ev.xbutton.y > button_drag_start_y - H_SWIPE_Y_DEVIATION && ev.xbutton.y < button_drag_start_y + H_SWIPE_Y_DEVIATION) + ){ + // left swipe + wm_activate_client(stack_cycle_backward(w, MBCLIENT_TYPE_APP)); + } else if(button_window_y + ev.xbutton.y > button_drag_start_y + V_SWIPE_Y_DEVIATION + && (ev.xbutton.x > button_drag_start_x - V_SWIPE_X_DEVIATION && ev.xbutton.x < button_drag_start_x + V_SWIPE_X_DEVIATION) + ){ + // down swipe + button_drag_client->iconize(button_drag_client); + } + } + } + break; case MapRequest: wm_handle_map_request(w, &ev.xmaprequest); break; case UnmapNotify: @@ -1072,6 +1329,7 @@ /* Pass the event on to the window class */ if (c) c->button_press(c,e); + button_drag_client = c; }