#include "layout.h"
#include "client.h"
#include "floating.h"
+#include "workspace.h"
/*
* Toggles floating mode for the given client.
Container *con = client->container;
i3Font *font = load_font(conn, config.font);
+ if (client->dock) {
+ LOG("Not putting dock client into floating mode\n");
+ return;
+ }
+
if (con == NULL) {
LOG("This client is already in floating (container == NULL), re-inserting\n");
Client *next_tiling;
- SLIST_FOREACH(next_tiling, &(client->workspace->focus_stack), focus_clients)
+ Workspace *ws = client->workspace;
+ SLIST_FOREACH(next_tiling, &(ws->focus_stack), focus_clients)
if (!client_is_floating(next_tiling))
break;
/* If there are no tiling clients on this workspace, there can only be one
* container: the first one */
- if (next_tiling == TAILQ_END(&(client->workspace->focus_stack)))
- con = client->workspace->table[0][0];
+ if (next_tiling == TAILQ_END(&(ws->focus_stack)))
+ con = ws->table[0][0];
else con = next_tiling->container;
/* Remove the client from the list of floating clients */
- TAILQ_REMOVE(&(client->workspace->floating_clients), client, floating_clients);
+ TAILQ_REMOVE(&(ws->floating_clients), client, floating_clients);
LOG("destination container = %p\n", con);
Client *old_focused = con->currently_focused;
TAILQ_INSERT_TAIL(&(client->workspace->floating_clients), client, floating_clients);
if (client->fullscreen)
client->workspace->fullscreen_client = client;
-
}
/*
/* fake_absolute_configure_notify flushes */
}
-
drag_pointer(conn, client, event, XCB_NONE, BORDER_TOP /* irrelevant */, drag_window_callback);
}
+/*
+ * Called when the user right-clicked on the titlebar of a floating window to
+ * resize it.
+ * Calls the drag_pointer function with the resize_window callback
+ *
+ */
+void floating_resize_window(xcb_connection_t *conn, Client *client, xcb_button_press_event_t *event) {
+ LOG("floating_resize_window\n");
+
+ void resize_window_callback(Rect *old_rect, uint32_t new_x, uint32_t new_y) {
+ int32_t new_width = old_rect->width + (new_x - event->root_x);
+ int32_t new_height = old_rect->height + (new_y - event->root_y);
+
+ /* Obey minimum window size and reposition the client */
+ if (new_width >= 50)
+ client->rect.width = new_width;
+
+ if (new_height >= 20)
+ client->rect.height = new_height;
+
+ /* resize_client flushes */
+ resize_client(conn, client);
+ }
+
+ drag_pointer(conn, client, event, XCB_NONE, BORDER_TOP /* irrelevant */, resize_window_callback);
+}
+
+
/*
* This function grabs your pointer and lets you drag stuff around (borders).
* Every time you move your mouse, an XCB_MOTION_NOTIFY event will be received
/* motion_notify events are saved for later */
FREE(last_motion_notify);
last_motion_notify = inside_event;
-
break;
+
+ case XCB_UNMAP_NOTIFY:
+ LOG("Unmap-notify, aborting\n");
+ xcb_event_handle(&evenths, inside_event);
+ goto done;
+
default:
LOG("Passing to original handler\n");
/* Use original handler */
void floating_move(xcb_connection_t *conn, Client *currently_focused, direction_t direction) {
LOG("floating move\n");
+ Rect destination = currently_focused->rect;
+ Rect *screen = &(currently_focused->workspace->screen->rect);
+
switch (direction) {
case D_LEFT:
- if (currently_focused->rect.x < 10)
- return;
- currently_focused->rect.x -= 10;
+ destination.x -= 10;
break;
case D_RIGHT:
- currently_focused->rect.x += 10;
+ destination.x += 10;
break;
case D_UP:
- if (currently_focused->rect.y < 10)
- return;
- currently_focused->rect.y -= 10;
+ destination.y -= 10;
break;
case D_DOWN:
- currently_focused->rect.y += 10;
+ destination.y += 10;
break;
/* to make static analyzers happy */
default:
break;
}
+ /* Prevent windows from vanishing completely */
+ if ((int32_t)(destination.x + destination.width - 5) <= (int32_t)screen->x ||
+ (int32_t)(destination.x + 5) >= (int32_t)(screen->x + screen->width) ||
+ (int32_t)(destination.y + destination.height - 5) <= (int32_t)screen->y ||
+ (int32_t)(destination.y + 5) >= (int32_t)(screen->y + screen->height)) {
+ LOG("boundary check failed, not moving\n");
+ return;
+ }
+
+ currently_focused->rect = destination;
reposition_client(conn, currently_focused);
/* Because reposition_client does not send a faked configure event (only resize does),
LOG("floating_hidden is now: %d\n", workspace->floating_hidden);
TAILQ_FOREACH(client, &(workspace->floating_clients), floating_clients) {
if (workspace->floating_hidden)
- xcb_unmap_window(conn, client->frame);
- else xcb_map_window(conn, client->frame);
+ client_unmap(conn, client);
+ else client_map(conn, client);
}
/* If we just unmapped all floating windows we should ensure that the focus