diff --git a/include/container.h b/include/container.h index 7560ddb86..3136e5656 100644 --- a/include/container.h +++ b/include/container.h @@ -36,6 +36,9 @@ struct sway_container { // Not including borders or margins int width, height; + // Used for setting floating geometry + int desired_width, desired_height; + int x, y; bool visible; @@ -62,6 +65,8 @@ swayc_t *new_workspace(swayc_t * output, const char *name); swayc_t *new_container(swayc_t *child, enum swayc_layouts layout); //Creates view as a sibling of current focused container, or as child of a workspace swayc_t *new_view(swayc_t *sibling, wlc_handle handle); +//Creates view as a new floating view which is in the active workspace +swayc_t *new_floating_view(wlc_handle handle); swayc_t *destroy_output(swayc_t *output); diff --git a/sway/commands.c b/sway/commands.c index 91dfa2b2c..8a81cd766 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -183,16 +183,19 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) { view->is_floating = true; for (i = 0; i < view->parent->children->length; i++) { if (view->parent->children->items[i] == view) { - // Cut down on width/height so it's obvious that you've gone floating - // if this is the only view - view->width = view->width - 30; - view->height = view->height - 30; + // Try to use desired geometry to set w/h + if (view->desired_width != -1) { + view->width = view->desired_width; + } + if (view->desired_height != -1) { + view->height = view->desired_height; + } // Swap from the list of whatever container the view was in // to the workspace->floating list - // TODO: Destroy any remaining empty containers list_del(view->parent->children, i); list_add(active_workspace->floating, view); + destroy_container(view->parent); // Set the new position of the container and arrange windows view->x = (active_workspace->width - view->width)/2; diff --git a/sway/container.c b/sway/container.c index 87e48e910..1f93d4dc5 100644 --- a/sway/container.c +++ b/sway/container.c @@ -135,6 +135,9 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { view->name = strdup(title); view->visible = true; + view->desired_width = -1; + view->desired_height = -1; + // TODO: properly set this view->is_floating = false; @@ -149,6 +152,38 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { return view; } +swayc_t *new_floating_view(wlc_handle handle) { + const char *title = wlc_view_get_title(handle); + swayc_t *view = new_swayc(C_VIEW); + sway_log(L_DEBUG, "Adding new view %u:%s as a floating view", + (unsigned int)handle, title); + //Setup values + view->handle = handle; + view->name = strdup(title); + view->visible = true; + + // Set the geometry of the floating view + const struct wlc_geometry* geometry = wlc_view_get_geometry(handle); + + view->x = geometry->origin.x; + view->y = geometry->origin.y; + view->width = geometry->size.w; + view->height = geometry->size.h; + + view->desired_width = -1; + view->desired_height = -1; + + view->is_floating = true; + + //Case of focused workspace, just create as child of it + list_add(active_workspace->floating, view); + view->parent = active_workspace; + if (active_workspace->focused == NULL) { + active_workspace->focused = view; + } + return view; +} + swayc_t *destroy_output(swayc_t *output) { if (output->children->length == 0) { diff --git a/sway/handlers.c b/sway/handlers.c index 3e83b8501..85df09f70 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -10,6 +10,7 @@ #include "handlers.h" #include "stringop.h" #include "workspace.h" +#include "container.h" static struct wlc_origin mouse_origin; @@ -88,17 +89,24 @@ 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); uint32_t type = wlc_view_get_type(handle); - //If override_redirect/unmanaged/popup/modal/splach + // If override_redirect/unmanaged/popup/modal/splach if (type) { sway_log(L_DEBUG,"Unmanaged window of type %x left alone", type); wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); if (type & WLC_BIT_UNMANAGED) { return true; } - //for things like Dmenu + // For things like Dmenu if (type & WLC_BIT_OVERRIDE_REDIRECT) { wlc_view_focus(handle); } + + // Float popups + if (type & WLC_BIT_POPUP) { + swayc_t *view = new_floating_view(handle); + focus_view(view); + arrange_windows(active_workspace, -1, -1); + } } else { swayc_t *view = new_view(focused, handle); //Set maximize flag for windows. @@ -118,6 +126,24 @@ static bool handle_view_created(wlc_handle handle) { static void handle_view_destroyed(wlc_handle handle) { sway_log(L_DEBUG, "Destroying window %u", (unsigned int)handle); + + // Properly handle unmanaged views + uint32_t type = wlc_view_get_type(handle); + if (type) { + wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); + sway_log(L_DEBUG,"Unmanaged window of type %x was destroyed", type); + if (type & WLC_BIT_UNMANAGED) { + focus_view(focus_pointer()); + arrange_windows(active_workspace, -1, -1); + return; + } + + if (type & WLC_BIT_OVERRIDE_REDIRECT) { + focus_view(focus_pointer()); + arrange_windows(active_workspace, -1, -1); + return; + } + } swayc_t *view = get_swayc_for_handle(handle, &root_container); swayc_t *parent; swayc_t *focused = get_focused_container(&root_container); @@ -135,8 +161,23 @@ static void handle_view_focus(wlc_handle view, bool focus) { return; } -static void handle_view_geometry_request(wlc_handle view, const struct wlc_geometry* geometry) { - // deny that shit +static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geometry* geometry) { + // 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 + swayc_t *view = get_swayc_for_handle(handle, &root_container); + if (view) { + if (view->is_floating) { + view->width = geometry->size.w; + view->height = geometry->size.h; + view->x = geometry->origin.x; + view->y = geometry->origin.y; + arrange_windows(view->parent, -1, -1); + } else { + view->desired_width = geometry->size.w; + view->desired_height = geometry->size.h; + } + } } static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { diff --git a/sway/layout.c b/sway/layout.c index c53b9dade..1bc650503 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -73,11 +73,12 @@ swayc_t *remove_child(swayc_t *parent, swayc_t *child) { break; } } - } - for (i = 0; i < parent->children->length; ++i) { - if (parent->children->items[i] == child) { - list_del(parent->children, i); - break; + } else { + for (i = 0; i < parent->children->length; ++i) { + if (parent->children->items[i] == child) { + list_del(parent->children, i); + break; + } } } if (parent->focused == child) {