Skip to content

Commit

Permalink
Simplify view state handling.
Browse files Browse the repository at this point in the history
Removes the double buffering of view resizes, as right now it's buggy
and complicated. Later need to think about how to have glitch free
buffer changes with better system. Lets focus on simple code for now.

Remove all movement / resize code from wlc and make window manager
handle this.

Changes wlc_view_set_geometry, it now takes edges bitmask, this
information is relayed to wl_shell clients, and also used to synchronize
buffer resizes with client.

See example.c for reference implementation on resizing and movement.
  • Loading branch information
Cloudef committed Aug 18, 2015
1 parent 500e25f commit 23f6c03
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 201 deletions.
166 changes: 144 additions & 22 deletions example/example.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,62 @@
#include <stdlib.h>
#include <wlc/wlc.h>
#include <chck/math/math.h>
#include <linux/input.h>

static struct {
struct {
wlc_handle view;
struct wlc_origin grab;
struct wlc_geometry geometry;
uint32_t edges;
} action;
} compositor;

static bool
start_interactive_action(wlc_handle view, const struct wlc_origin *origin)
{
const struct wlc_geometry *g;
if (compositor.action.view || !(g = wlc_view_get_geometry(view)))
return false;

compositor.action.view = view;
compositor.action.grab = *origin;
compositor.action.geometry = *g;
return true;
}

static void
start_interactive_move(wlc_handle view, const struct wlc_origin *origin)
{
start_interactive_action(view, origin);
}

static void
start_interactive_resize(wlc_handle view, uint32_t edges, const struct wlc_origin *origin)
{
if (!start_interactive_action(view, origin))
return;

const int32_t halfw = compositor.action.geometry.origin.x + compositor.action.geometry.size.w / 2;
const int32_t halfh = compositor.action.geometry.origin.y + compositor.action.geometry.size.h / 2;

if (!(compositor.action.edges = edges)) {
compositor.action.edges = (origin->x < halfw ? WLC_RESIZE_EDGE_LEFT : (origin->x > halfw ? WLC_RESIZE_EDGE_RIGHT : 0)) |
(origin->y < halfh ? WLC_RESIZE_EDGE_TOP : (origin->y > halfh ? WLC_RESIZE_EDGE_BOTTOM : 0));
}

wlc_view_set_state(view, WLC_BIT_RESIZING, true);
}

static void
stop_interactive_action(void)
{
if (!compositor.action.view)
return;

wlc_view_set_state(compositor.action.view, WLC_BIT_RESIZING, false);
memset(&compositor.action, 0, sizeof(compositor.action));
}

static wlc_handle
get_topmost(wlc_handle output, size_t offset)
Expand All @@ -25,24 +81,11 @@ relayout(wlc_handle output)
uint32_t w = r->w / 2, h = r->h / chck_maxu32((1 + memb) / 2, 1);
for (size_t i = 0; i < memb; ++i) {
struct wlc_geometry g = { { (toggle ? w : 0), y }, { (!toggle && i == memb - 1 ? r->w : w), h } };
wlc_view_set_geometry(views[i], &g);
wlc_view_set_geometry(views[i], 0, &g);
y = y + (!(toggle = !toggle) ? h : 0);
}
}

static bool
output_created(wlc_handle output)
{
printf("created output (%zu)\n", output);
return true;
}

static void
output_destroyed(wlc_handle output)
{
printf("destroyed output (%zu)\n", output);
}

static void
output_resolution(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to)
{
Expand All @@ -53,7 +96,6 @@ output_resolution(wlc_handle output, const struct wlc_size *from, const struct w
static bool
view_created(wlc_handle view)
{
printf("created view (%zu)\n", view);
wlc_view_bring_to_front(view);
wlc_view_focus(view);
relayout(wlc_view_get_output(view));
Expand All @@ -63,7 +105,6 @@ view_created(wlc_handle view)
static void
view_destroyed(wlc_handle view)
{
printf("destroyed view (%zu)\n", view);
wlc_view_focus(get_topmost(wlc_view_get_output(view), 0));
relayout(wlc_view_get_output(view));
}
Expand All @@ -74,6 +115,18 @@ view_focus(wlc_handle view, bool focus)
wlc_view_set_state(view, WLC_BIT_ACTIVATED, focus);
}

static void
view_request_move(wlc_handle view, const struct wlc_origin *origin)
{
start_interactive_move(view, origin);
}

static void
view_request_resize(wlc_handle view, uint32_t edges, const struct wlc_origin *origin)
{
start_interactive_resize(view, edges, origin);
}

static bool
keyboard_key(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, uint32_t key, uint32_t sym, enum wlc_key_state state)
{
Expand All @@ -89,40 +142,108 @@ keyboard_key(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifie
wlc_view_focus(get_topmost(wlc_view_get_output(view), 0));
return true;
}
} else if (modifiers->mods & WLC_BIT_MOD_CTRL && sym == XKB_KEY_Escape) {
}

if (modifiers->mods & WLC_BIT_MOD_CTRL && sym == XKB_KEY_Escape) {
wlc_terminate();
return true;
} else if (modifiers->mods & WLC_BIT_MOD_CTRL && sym == XKB_KEY_Return) {
char *terminal = (getenv("TERMINAL") ? getenv("TERMINAL") : "weston-terminal");
wlc_exec(terminal, (char *const[]){ terminal, NULL });
return true;
}
}

return false;
}

static bool
pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, uint32_t button, enum wlc_button_state state)
pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, uint32_t button, enum wlc_button_state state, const struct wlc_origin *origin)
{
(void)button, (void)time, (void)modifiers;

if (state == WLC_BUTTON_STATE_PRESSED)
if (state == WLC_BUTTON_STATE_PRESSED) {
wlc_view_focus(view);
if (view) {
if (modifiers->mods & WLC_BIT_MOD_CTRL && button == BTN_LEFT)
start_interactive_move(view, origin);
if (modifiers->mods & WLC_BIT_MOD_CTRL && button == BTN_RIGHT)
start_interactive_resize(view, 0, origin);
}
} else {
stop_interactive_action();
}

return false;
return (compositor.action.view ? true : false);
}

static bool
pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_origin *origin)
{
(void)handle, (void)time;

if (compositor.action.view) {
struct wlc_geometry *g = &compositor.action.geometry;

if (compositor.action.edges) {
const struct wlc_size min = { 80, 40 };
const int32_t wd = chck_max32(0, origin->x - g->origin.x);
const int32_t hd = chck_max32(0, origin->y - g->origin.y);

if (compositor.action.edges & WLC_RESIZE_EDGE_LEFT) {
const uint32_t tw = chck_max32(0, g->size.w - (origin->x - g->origin.x));
g->size.w = chck_maxu32(min.w, tw);
g->origin.x = (g->size.w > min.w ? origin->x : g->origin.x);
} else if (compositor.action.edges & WLC_RESIZE_EDGE_RIGHT) {
g->size.w = chck_maxu32(min.w, wd);
}

if (compositor.action.edges & WLC_RESIZE_EDGE_TOP) {
const uint32_t th = chck_max32(0, g->size.h - (origin->y - g->origin.y));
g->size.h = chck_maxu32(min.h, th);
g->origin.y = (g->size.h > min.h ? origin->y : g->origin.y);
} else if (compositor.action.edges & WLC_RESIZE_EDGE_BOTTOM) {
g->size.h = chck_maxu32(min.h, hd);
}

const struct wlc_geometry *c;
if ((c = wlc_view_get_geometry(compositor.action.view))) {
const struct wlc_geometry r = { g->origin, g->size };
wlc_view_set_geometry(compositor.action.view, compositor.action.edges, &r);
}
} else {
const int32_t dx = origin->x - compositor.action.grab.x;
const int32_t dy = origin->y - compositor.action.grab.y;

g->origin.x += dx;
g->origin.y += dy;

wlc_view_set_geometry(compositor.action.view, 0, g);
}

compositor.action.grab = *origin;
}

return (compositor.action.view ? true : false);
}

int
main(int argc, char *argv[])
{
static struct wlc_interface interface = {
.output = {
.created = output_created,
.destroyed = output_destroyed,
.resolution = output_resolution,
},

.view = {
.created = view_created,
.destroyed = view_destroyed,
.focus = view_focus,

.request = {
.move = view_request_move,
.resize = view_request_resize,
},
},

.keyboard = {
Expand All @@ -131,6 +252,7 @@ main(int argc, char *argv[])

.pointer = {
.button = pointer_button,
.motion = pointer_motion,
},
};

Expand Down
23 changes: 21 additions & 2 deletions include/wlc/wlc.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,19 @@ enum wlc_view_type_bit {
WLC_BIT_POPUP = 1<<4, // xdg-shell, wl-shell popups
};

/** wlc_view_set_geometry(); Edges in interface interface.view.request.resize function. */
enum wlc_resize_edge {
WLC_RESIZE_EDGE_NONE = 0,
WLC_RESIZE_EDGE_TOP = 1,
WLC_RESIZE_EDGE_BOTTOM = 2,
WLC_RESIZE_EDGE_LEFT = 4,
WLC_RESIZE_EDGE_TOP_LEFT = 5,
WLC_RESIZE_EDGE_BOTTOM_LEFT = 6,
WLC_RESIZE_EDGE_RIGHT = 8,
WLC_RESIZE_EDGE_TOP_RIGHT = 9,
WLC_RESIZE_EDGE_BOTTOM_RIGHT = 10,
};

/** Mods in interface.keyboard.key function. */
enum wlc_modifier_bit {
WLC_BIT_MOD_SHIFT = 1<<0,
Expand Down Expand Up @@ -158,6 +171,12 @@ struct wlc_interface {

/** Request to disable or enable the given state for view. Apply using wlc_view_set_state to agree. */
void (*state)(wlc_handle view, enum wlc_view_state_bit, bool toggle);

/** Request to move itself. Start a interactive move to agree. */
void (*move)(wlc_handle view, const struct wlc_origin *origin);

/** Request to resize itself with the given edges. Start a interactive resize to agree. */
void (*resize)(wlc_handle view, uint32_t edges, const struct wlc_origin *origin);
} request;
} view;

Expand Down Expand Up @@ -334,8 +353,8 @@ void wlc_view_set_mask(wlc_handle view, uint32_t mask);
/** Get current geometry. */
const struct wlc_geometry* wlc_view_get_geometry(wlc_handle view);

/** Set geometry. */
void wlc_view_set_geometry(wlc_handle view, const struct wlc_geometry *geometry);
/** Set geometry. Set edges if the geometry change is caused by interactive resize. */
void wlc_view_set_geometry(wlc_handle view, uint32_t edges, const struct wlc_geometry *geometry);

/** Get type bitfield. */
uint32_t wlc_view_get_type(wlc_handle view);
Expand Down
Loading

0 comments on commit 23f6c03

Please sign in to comment.