aboutsummaryrefslogtreecommitdiff
path: root/sway/handlers.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/handlers.c')
-rw-r--r--sway/handlers.c326
1 files changed, 182 insertions, 144 deletions
diff --git a/sway/handlers.c b/sway/handlers.c
index 534b4e4f..79628fe5 100644
--- a/sway/handlers.c
+++ b/sway/handlers.c
@@ -13,21 +13,14 @@
#include "workspace.h"
#include "container.h"
#include "focus.h"
-
-uint32_t keys_pressed[32];
+#include "input_state.h"
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
- swayc_t *parent = view;
- while (parent->type != C_OUTPUT) {
- parent = parent->parent;
- }
+ swayc_t *parent = swayc_parent_by_type(view, C_OUTPUT);
if (origin->x >= view->x && origin->y >= view->y
&& origin->x < view->x + view->width && origin->y < view->y + view->height
&& view->visible && parent == root_container.focused) {
@@ -86,10 +79,12 @@ swayc_t *container_under_pointer(void) {
return lookup;
}
+/* Handles */
+
static bool handle_output_created(wlc_handle output) {
swayc_t *op = new_output(output);
- //Switch to workspace if we need to
+ // Switch to workspace if we need to
if (active_workspace == NULL) {
swayc_t *ws = op->children->items[0];
workspace_switch(ws);
@@ -111,7 +106,7 @@ static void handle_output_destroyed(wlc_handle output) {
if (list->length == 0) {
active_workspace = NULL;
} else {
- //switch to other outputs active workspace
+ // switch to other outputs active workspace
workspace_switch(((swayc_t *)root_container.children->items[0])->focused);
}
}
@@ -137,38 +132,64 @@ static void handle_output_focused(wlc_handle output, bool focus) {
}
static bool handle_view_created(wlc_handle handle) {
- swayc_t *focused = get_focused_container(&root_container);
+ // if view is child of another view, the use that as focused container
+ wlc_handle parent = wlc_view_get_parent(handle);
+ swayc_t *focused = NULL;
swayc_t *newview = NULL;
+
+ // Get parent container, to add view in
+ if (parent) {
+ focused = get_swayc_for_handle(parent, &root_container);
+ }
+ if (!focused || focused->type == C_OUTPUT) {
+ focused = get_focused_container(&root_container);
+ }
+ sway_log(L_DEBUG, "handle:%ld type:%x state:%x parent:%ld "
+ "mask:%d (x:%d y:%d w:%d h:%d) title:%s "
+ "class:%s appid:%s",
+ handle, wlc_view_get_type(handle), wlc_view_get_state(handle), parent,
+ wlc_view_get_mask(handle), wlc_view_get_geometry(handle)->origin.x,
+ wlc_view_get_geometry(handle)->origin.y,wlc_view_get_geometry(handle)->size.w,
+ wlc_view_get_geometry(handle)->size.h, wlc_view_get_title(handle),
+ wlc_view_get_class(handle), wlc_view_get_app_id(handle));
+
+ // TODO properly figure out how each window should be handled.
switch (wlc_view_get_type(handle)) {
// regular view created regularly
case 0:
newview = new_view(focused, handle);
wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true);
break;
- // takes keyboard focus
+
+ // Dmenu keeps viewfocus, but others with this flag dont, for now simulate
+ // dmenu
case WLC_BIT_OVERRIDE_REDIRECT:
- sway_log(L_DEBUG, "view %ld with OVERRIDE_REDIRECT", handle);
- locked_view_focus = true;
+// locked_view_focus = true;
wlc_view_focus(handle);
wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true);
wlc_view_bring_to_front(handle);
break;
- // Takes container focus
+
+ // Firefox popups have this flag set.
case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED:
- sway_log(L_DEBUG, "view %ld with OVERRIDE_REDIRECT|WLC_BIT_MANAGED", handle);
wlc_view_bring_to_front(handle);
locked_container_focus = true;
break;
- // set modals as floating containers
+
+ // Modals, get focus, popups do not
case WLC_BIT_MODAL:
+ wlc_view_focus(handle);
wlc_view_bring_to_front(handle);
newview = new_floating_view(handle);
case WLC_BIT_POPUP:
+ wlc_view_bring_to_front(handle);
break;
}
+
if (newview) {
set_focused_container(newview);
- arrange_windows(newview->parent, -1, -1);
+ swayc_t *output = swayc_parent_by_type(newview, C_OUTPUT);
+ arrange_windows(output, -1, -1);
}
return true;
}
@@ -181,19 +202,19 @@ static void handle_view_destroyed(wlc_handle handle) {
// regular view created regularly
case 0:
case WLC_BIT_MODAL:
+ case WLC_BIT_POPUP:
if (view) {
swayc_t *parent = destroy_view(view);
arrange_windows(parent, -1, -1);
}
break;
- // takes keyboard focus
+ // DMENU has this flag, and takes view_focus, but other things with this
+ // flag dont
case WLC_BIT_OVERRIDE_REDIRECT:
- locked_view_focus = false;
+// locked_view_focus = false;
break;
- // 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));
@@ -205,7 +226,7 @@ static void handle_view_focus(wlc_handle view, bool focus) {
static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geometry *geometry) {
sway_log(L_DEBUG, "geometry request %d x %d : %d x %d",
- geometry->origin.x, geometry->origin.y, geometry->size.w,geometry->size.h);
+ geometry->origin.x, geometry->origin.y, geometry->size.w, geometry->size.h);
// If the view is floating, then apply the geometry.
// Otherwise save the desired width/height for the view.
// This will not do anything for the time being as WLC improperly sends geometry requests
@@ -225,21 +246,17 @@ static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geo
}
static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) {
- swayc_t *c = NULL;
- switch(state) {
+ swayc_t *c = get_swayc_for_handle(view, &root_container);
+ switch (state) {
case WLC_BIT_FULLSCREEN:
// i3 just lets it become fullscreen
wlc_view_set_state(view, state, toggle);
- c = get_swayc_for_handle(view, &root_container);
- sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d",view,c->name,toggle);
if (c) {
+ sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d", view, c->name, toggle);
arrange_windows(c->parent, -1, -1);
// Set it as focused window for that workspace if its going fullscreen
if (toggle) {
- swayc_t *ws = c;
- while (ws->type != C_WORKSPACE) {
- ws = ws->parent;
- }
+ swayc_t *ws = swayc_parent_by_type(c, C_WORKSPACE);
// Set ws focus to c
set_focused_container_for(ws, c);
}
@@ -248,7 +265,9 @@ static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit s
case WLC_BIT_MAXIMIZED:
case WLC_BIT_RESIZING:
case WLC_BIT_MOVING:
+ break;
case WLC_BIT_ACTIVATED:
+ sway_log(L_DEBUG, "View %p requested to be activated", c);
break;
}
return;
@@ -257,29 +276,38 @@ static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit s
static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers,
uint32_t key, uint32_t sym, enum wlc_key_state state) {
- enum { QSIZE = 32 };
+
if (locked_view_focus && state == WLC_KEY_STATE_PRESSED) {
return false;
}
- static uint8_t head = 0;
- bool cmd_success = false;
+
+ // Revert floating container back to original position on keypress
+ if (state == WLC_KEY_STATE_PRESSED &&
+ (pointer_state.floating.drag || pointer_state.floating.resize)) {
+ reset_floating(get_focused_view(&root_container));
+ }
struct sway_mode *mode = config->current_mode;
+
+ if (sym < 70000 /* bullshit made up number */) {
+ if (!isalnum(sym) && sym != ' ' && sym != XKB_KEY_Escape && sym != XKB_KEY_Tab) {
+ // God fucking dammit
+ return false;
+ }
+ }
+
// Lowercase if necessary
sym = tolower(sym);
- // Find key, if it has been pressed
- int mid = 0;
- while (mid < head && keys_pressed[mid] != sym) {
- ++mid;
- }
- if (state == WLC_KEY_STATE_PRESSED && mid == head && head + 1 < QSIZE) {
- keys_pressed[head++] = sym;
- } else if (state == WLC_KEY_STATE_RELEASED && mid < head) {
- memmove(keys_pressed + mid, keys_pressed + mid + 1, sizeof*keys_pressed * (--head - mid));
+ int i;
+
+ if (state == WLC_KEY_STATE_PRESSED) {
+ press_key(sym);
+ } else { // WLC_KEY_STATE_RELEASED
+ release_key(sym);
}
+
// TODO: reminder to check conflicts with mod+q+a versus mod+q
- int i;
for (i = 0; i < mode->bindings->length; ++i) {
struct sway_binding *binding = mode->bindings->items[i];
@@ -287,39 +315,22 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier
bool match;
int j;
for (j = 0; j < binding->keys->length; ++j) {
- match = false;
xkb_keysym_t *key = binding->keys->items[j];
- uint8_t k;
- for (k = 0; k < head; ++k) {
- if (keys_pressed[k] == *key) {
- match = true;
- break;
- }
- }
- if (match == false) {
+ if ((match = check_key(*key)) == false) {
break;
}
}
-
if (match) {
- // 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(keys_pressed + k, keys_pressed + k + 1, sizeof*keys_pressed * (--head - k));
- break;
- }
- }
if (state == WLC_KEY_STATE_PRESSED) {
- cmd_success = handle_command(config, binding->command);
+ handle_command(config, binding->command);
+ return true;
} else if (state == WLC_KEY_STATE_RELEASED) {
// TODO: --released
}
}
}
}
- return cmd_success;
+ return false;
}
static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_origin *origin) {
@@ -327,119 +338,129 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct
static wlc_handle prev_handle = 0;
mouse_origin = *origin;
bool changed_floating = false;
- int i = 0;
if (!active_workspace) {
return false;
}
// Do checks to determine if proper keys are being held
- swayc_t *view = active_workspace->focused;
- if (m1_held && view) {
+ swayc_t *view = get_focused_view(active_workspace);
+ uint32_t edge = 0;
+ if (pointer_state.floating.drag && view) {
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;
- }
- }
+ int dx = mouse_origin.x - prev_pos.x;
+ int dy = mouse_origin.y - prev_pos.y;
+ view->x += dx;
+ view->y += dy;
+ changed_floating = true;
}
- } else if (m2_held && view) {
+ } else if (pointer_state.floating.resize && view) {
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) {
+ int dx = mouse_origin.x - prev_pos.x;
+ int dy = mouse_origin.y - prev_pos.y;
+ int min_sane_w = 100;
+ int min_sane_h = 60;
+
+ // 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) {
+ if (!pointer_state.lock.right) {
+ if (view->width > min_sane_w) {
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){
+ view->width += dx;
+ edge += WLC_RESIZE_EDGE_RIGHT;
+ }
+ } else if (mouse_origin.x < midway_x && !pointer_state.lock.left) {
+ changed_floating = true;
+ view->x += dx;
+ view->width -= dx;
+ edge += WLC_RESIZE_EDGE_LEFT;
+ }
+ } else if (dx > 0) {
+ if (mouse_origin.x > midway_x && !pointer_state.lock.right) {
+ changed_floating = true;
+ view->width += dx;
+ edge += WLC_RESIZE_EDGE_RIGHT;
+ } else if (!pointer_state.lock.left) {
+ if (view->width > min_sane_w) {
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;
- }
+ view->x += dx;
+ view->width -= dx;
+ edge += WLC_RESIZE_EDGE_LEFT;
}
+ }
+ }
- if (dy < 0) {
+ if (dy < 0) {
+ if (!pointer_state.lock.bottom) {
+ if (view->height > min_sane_h) {
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) {
+ view->height += dy;
+ edge += WLC_RESIZE_EDGE_BOTTOM;
+ }
+ } else if (mouse_origin.y < midway_y && !pointer_state.lock.top) {
+ changed_floating = true;
+ view->y += dy;
+ view->height -= dy;
+ edge += WLC_RESIZE_EDGE_TOP;
+ }
+ } else if (dy > 0) {
+ if (mouse_origin.y > midway_y && !pointer_state.lock.bottom) {
+ changed_floating = true;
+ view->height += dy;
+ edge += WLC_RESIZE_EDGE_BOTTOM;
+ } else if (!pointer_state.lock.top) {
+ if (view->height > min_sane_h) {
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;
- }
+ view->y += dy;
+ view->height -= dy;
+ edge += WLC_RESIZE_EDGE_TOP;
}
- break;
}
}
}
}
if (config->focus_follows_mouse && prev_handle != handle) {
- //Dont change focus if fullscreen
+ // Dont change focus if fullscreen
swayc_t *focused = get_focused_view(view);
- if (!(focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN)) {
+ if (!(focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN)
+ && !(pointer_state.l_held || pointer_state.r_held)) {
set_focused_container(container_under_pointer());
}
}
prev_handle = handle;
prev_pos = mouse_origin;
if (changed_floating) {
- arrange_windows(view, -1, -1);
+ struct wlc_geometry geometry = {
+ .origin = {
+ .x = view->x,
+ .y = view->y
+ },
+ .size = {
+ .w = view->width,
+ .h = view->height
+ }
+ };
+ wlc_view_set_geometry(view->handle, edge, &geometry);
return true;
}
return false;
}
+
static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers,
- uint32_t button, enum wlc_button_state state) {
+ uint32_t button, enum wlc_button_state state, const struct wlc_origin *origin) {
swayc_t *focused = get_focused_container(&root_container);
- //dont change focus if fullscreen
+ // dont change focus if fullscreen
if (focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) {
return false;
}
if (state == WLC_BUTTON_STATE_PRESSED) {
sway_log(L_DEBUG, "Mouse button %u pressed", button);
- if (button == 272) {
- m1_held = true;
+ if (button == M_LEFT_CLICK) {
+ pointer_state.l_held = true;
}
- if (button == 273) {
- m2_held = true;
+ if (button == M_RIGHT_CLICK) {
+ pointer_state.r_held = true;
}
swayc_t *pointer = container_under_pointer();
set_focused_container(pointer);
@@ -453,15 +474,32 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w
}
}
arrange_windows(pointer->parent, -1, -1);
+ if (modifiers->mods & config->floating_mod) {
+ int midway_x = pointer->x + pointer->width/2;
+ int midway_y = pointer->y + pointer->height/2;
+
+ pointer_state.floating.drag = pointer_state.l_held;
+ pointer_state.floating.resize = pointer_state.r_held;
+ pointer_state.lock.bottom = origin->y < midway_y;
+ pointer_state.lock.top = !pointer_state.lock.bottom;
+ pointer_state.lock.right = origin->x < midway_x;
+ pointer_state.lock.left = !pointer_state.lock.right;
+ start_floating(pointer);
+ }
+ // Dont want pointer sent to window while dragging or resizing
+ return (pointer_state.floating.drag || pointer_state.floating.resize);
}
return (pointer && pointer != focused);
} else {
sway_log(L_DEBUG, "Mouse button %u released", button);
- if (button == 272) {
- m1_held = false;
+ if (button == M_LEFT_CLICK) {
+ pointer_state.l_held = false;
+ pointer_state.floating.drag = false;
}
- if (button == 273) {
- m2_held = false;
+ if (button == M_RIGHT_CLICK) {
+ pointer_state.r_held = false;
+ pointer_state.floating.resize = false;
+ pointer_state.lock = (struct pointer_lock){false ,false ,false ,false};
}
}
return false;