diff --git a/include/config.h b/include/config.h index 38e93eb8..b9511aac 100644 --- a/include/config.h +++ b/include/config.h @@ -3,6 +3,7 @@ #include #include +#include #include "list.h" struct sway_variable { @@ -32,6 +33,7 @@ struct sway_config { list_t *cmd_queue; list_t *workspace_outputs; struct sway_mode *current_mode; + uint32_t floating_mod; // Flags bool focus_follows_mouse; diff --git a/include/handlers.h b/include/handlers.h index 6ea4bbf1..6b642419 100644 --- a/include/handlers.h +++ b/include/handlers.h @@ -5,7 +5,9 @@ #include extern struct wlc_interface interface; +extern uint32_t keys_pressed[32]; +//set focus to current pointer location and return focused container swayc_t *container_under_pointer(void); #endif diff --git a/sway/commands.c b/sway/commands.c index 134593c7..548cb8ed 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -171,6 +171,10 @@ static bool cmd_exit(struct sway_config *config, int argc, char **argv) { } static bool cmd_floating(struct sway_config *config, int argc, char **argv) { + if (!checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1)) { + return false; + } + if (strcasecmp(argv[0], "toggle") == 0) { swayc_t *view = get_focused_container(&root_container); // Prevent running floating commands on things like workspaces @@ -242,6 +246,14 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) { return true; } +static bool cmd_floating_mod(struct sway_config *config, int argc, char **argv) { + if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1)) { + return false; + } + config->floating_mod = xkb_keysym_from_name(argv[0], XKB_KEYSYM_CASE_INSENSITIVE); + return true; +} + static bool cmd_focus(struct sway_config *config, int argc, char **argv) { if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1)) { return false; @@ -466,6 +478,7 @@ static struct cmd_handler handlers[] = { { "exec_always", cmd_exec_always }, { "exit", cmd_exit }, { "floating", cmd_floating }, + { "floating_modifier", cmd_floating_mod }, { "focus", cmd_focus }, { "focus_follows_mouse", cmd_focus_follows_mouse }, { "fullscreen", cmd_fullscreen }, diff --git a/sway/handlers.c b/sway/handlers.c index d18be253..2a5113cc 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -14,8 +14,13 @@ #include "container.h" #include "focus.h" +uint32_t keys_pressed[32]; + static struct wlc_origin mouse_origin; +static bool m1_held = false; +static bool m2_held = false; + static bool pointer_test(swayc_t *view, void *_origin) { const struct wlc_origin *origin = _origin; //Determine the output that the view is under @@ -144,10 +149,10 @@ static bool handle_view_created(wlc_handle handle) { locked_container_focus = true; break; //set modals as floating containers - case WLC_BIT_POPUP: case WLC_BIT_MODAL: wlc_view_bring_to_front(handle); newview = new_floating_view(handle); + case WLC_BIT_POPUP: break; } if (newview) { @@ -166,9 +171,9 @@ static void handle_view_destroyed(wlc_handle handle) { //regular view created regularly case 0: case WLC_BIT_MODAL: - case WLC_BIT_POPUP: if (view) { - arrange_windows(destroy_view(view), -1, -1); + swayc_t *parent = destroy_view(view); + arrange_windows(parent, -1, -1); if (!focused || focused == view) { set_focused_container(container_under_pointer()); } @@ -181,6 +186,7 @@ static void handle_view_destroyed(wlc_handle handle) { //Takes container focus case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED: locked_container_focus = false; + case WLC_BIT_POPUP: break; } set_focused_container(get_focused_view(&root_container)); @@ -250,7 +256,6 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier return false; } static uint8_t head = 0; - static uint32_t array[QSIZE]; bool cmd_success = false; struct sway_mode *mode = config->current_mode; @@ -259,13 +264,13 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier //Find key, if it has been pressed int mid = 0; - while (mid < head && array[mid] != sym) { + while (mid < head && keys_pressed[mid] != sym) { ++mid; } if (state == WLC_KEY_STATE_PRESSED && mid == head && head + 1 < QSIZE) { - array[head++] = sym; + keys_pressed[head++] = sym; } else if (state == WLC_KEY_STATE_RELEASED && mid < head) { - memmove(array + mid, array + mid + 1, sizeof*array * (--head - mid)); + memmove(keys_pressed + mid, keys_pressed + mid + 1, sizeof*keys_pressed * (--head - mid)); } // TODO: reminder to check conflicts with mod+q+a versus mod+q int i; @@ -280,7 +285,7 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier xkb_keysym_t *key = binding->keys->items[j]; uint8_t k; for (k = 0; k < head; ++k) { - if (array[k] == *key) { + if (keys_pressed[k] == *key) { match = true; break; } @@ -291,12 +296,12 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier } if (match) { - //Remove matched keys from array + //Remove matched keys from keys_pressed int j; for (j = 0; j < binding->keys->length; ++j) { uint8_t k; for (k = 0; k < head; ++k) { - memmove(array + k, array + k + 1, sizeof*array * (--head - k)); + memmove(keys_pressed + k, keys_pressed + k + 1, sizeof*keys_pressed * (--head - k)); break; } } @@ -311,13 +316,100 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier return cmd_success; } -static bool handle_pointer_motion(wlc_handle view, uint32_t time, const struct wlc_origin *origin) { - static wlc_handle prev_view = 0; +static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_origin *origin) { + static struct wlc_origin prev_pos; + static wlc_handle prev_handle = 0; mouse_origin = *origin; - if (config->focus_follows_mouse && prev_view != view) { + bool changed_floating = false; + int i = 0; + // Do checks to determine if proper keys are being held + swayc_t *view = active_workspace->focused; + if (m1_held) { + if (view->is_floating) { + while (keys_pressed[i++]) { + if (keys_pressed[i] == config->floating_mod) { + int dx = mouse_origin.x - prev_pos.x; + int dy = mouse_origin.y - prev_pos.y; + sway_log(L_DEBUG, "Moving from px: %d to cx: %d and from py: %d to cy: %d", prev_pos.x, mouse_origin.x, prev_pos.y, mouse_origin.y); + sway_log(L_DEBUG, "Moving: dx: %d, dy: %d", dx, dy); + + view->x += dx; + view->y += dy; + changed_floating = true; + break; + } + } + } + } else if (m2_held) { + if (view->is_floating) { + while (keys_pressed[i++]) { + if (keys_pressed[i] == config->floating_mod) { + int dx = mouse_origin.x - prev_pos.x; + int dy = mouse_origin.y - prev_pos.y; + sway_log(L_DEBUG, "Moving from px: %d to cx: %d and from py: %d to cy: %d", prev_pos.x, mouse_origin.x, prev_pos.y, mouse_origin.y); + sway_log(L_INFO, "Moving: dx: %d, dy: %d", dx, dy); + + // Move and resize the view based on the dx/dy and mouse position + int midway_x = view->x + view->width/2; + int midway_y = view->y + view->height/2; + + if (dx < 0) { + changed_floating = true; + if (mouse_origin.x > midway_x) { + sway_log(L_INFO, "Downsizing view to the left"); + view->width += dx; + } else { + sway_log(L_INFO, "Upsizing view to the left"); + view->x += dx; + view->width -= dx; + } + } else if (dx > 0){ + changed_floating = true; + if (mouse_origin.x > midway_x) { + sway_log(L_INFO, "Upsizing to the right"); + view->width += dx; + } else { + sway_log(L_INFO, "Downsizing to the right"); + view->x += dx; + view->width -= dx; + } + } + + if (dy < 0) { + changed_floating = true; + if (mouse_origin.y > midway_y) { + sway_log(L_INFO, "Downsizing view to the top"); + view->height += dy; + } else { + sway_log(L_INFO, "Upsizing the view to the top"); + view->y += dy; + view->height -= dy; + } + } else if (dy > 0) { + changed_floating = true; + if (mouse_origin.y > midway_y) { + sway_log(L_INFO, "Upsizing to the bottom"); + view->height += dy; + } else { + sway_log(L_INFO, "Downsizing to the bottom"); + view->y += dy; + view->height -= dy; + } + } + break; + } + } + } + } + if (config->focus_follows_mouse && prev_handle != handle) { set_focused_container(container_under_pointer()); } - prev_view = view; + prev_handle = handle; + prev_pos = mouse_origin; + if (changed_floating) { + arrange_windows(view, -1, -1); + return true; + } return false; } @@ -325,9 +417,24 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w uint32_t button, enum wlc_button_state state) { swayc_t *focused = get_focused_container(&root_container); if (state == WLC_BUTTON_STATE_PRESSED) { + sway_log(L_DEBUG, "Mouse button %u pressed", button); + if (button == 272) { + m1_held = true; + } + if (button == 273) { + m2_held = true; + } swayc_t *pointer = container_under_pointer(); set_focused_container(pointer); return (pointer && pointer != focused); + } else { + sway_log(L_DEBUG, "Mouse button %u released", button); + if (button == 272) { + m1_held = false; + } + if (button == 273) { + m2_held = false; + } } return false; }