text:
#define _XOPEN_SOURCE 700
#include <math.h>
#ifdef __linux__
#include <linux/input-event-codes.h>
#elif __FreeBSD__
#include <dev/evdev/input-event-codes.h>
#endif
#include <limits.h>
#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_xcursor_manager.h>
#include <wlr/types/wlr_idle.h>
#include "list.h"
#include "log.h"
#include "config.h"
#include "sway/commands.h"
#include "sway/desktop.h"
#include "sway/desktop/transaction.h"
#include "sway/input/cursor.h"
#include "sway/input/keyboard.h"
#include "sway/layers.h"
#include "sway/output.h"
#include "sway/tree/arrange.h"
#include "sway/tree/root.h"
#include "sway/tree/view.h"
#include "sway/tree/workspace.h"
#include "wlr-layer-shell-unstable-v1-protocol.h"

static uint32_t get_current_time_msec() {
	struct timespec now;
	clock_gettime(CLOCK_MONOTONIC, &now);
	return now.tv_nsec / 1000;
}

static struct wlr_surface *layer_surface_at(struct sway_output *output,
		struct wl_list *layer, double ox, double oy, double *sx, double *sy) {
	struct sway_layer_surface *sway_layer;
	wl_list_for_each_reverse(sway_layer, layer, link) {
		struct wlr_surface *wlr_surface =
			sway_layer->layer_surface->surface;
		double _sx = ox - sway_layer->geo.x;
		double _sy = oy - sway_layer->geo.y;
		// TODO: Test popups/subsurfaces
		if (wlr_surface_point_accepts_input(wlr_surface, _sx, _sy)) {
			*sx = _sx;
			*sy = _sy;
			return wlr_surface;
		}
	}
	return NULL;
}

/**
 * Returns the container at the cursor's position. If there is a surface at that
 * location, it is stored in **surface (it may not be a view).
 */
static struct sway_container *container_at_coords(
		struct sway_seat *seat, double lx, double ly,
		struct wlr_surface **surface, double *sx, double *sy) {
	// check for unmanaged views first
#ifdef HAVE_XWAYLAND
	struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged;
	struct sway_xwayland_unmanaged *unmanaged_surface;
	wl_list_for_each_reverse(unmanaged_surface, unmanaged, link) {
		struct wlr_xwayland_surface *xsurface =
			unmanaged_surface->wlr_xwayland_surface;

		double _sx = lx - unmanaged_surface->lx;
		double _sy = ly - unmanaged_surface->ly;
		if (wlr_surface_point_accepts_input(xsurface->surface, _sx, _sy)) {
			*surface = xsurface->surface;
			*sx = _sx;
			*sy = _sy;
			return NULL;
		}
	}
#endif
	// find the output the cursor is on
	struct wlr_output_layout *output_layout =
		root_container.sway_root->output_layout;
	struct wlr_output *wlr_output = wlr_output_layout_output_at(
			output_layout, lx, ly);
	if (wlr_output == NULL) {
		return NULL;
	}
	struct sway_output *output = wlr_output->data;
	double ox = lx, oy = ly;
	wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy);

	// find the focused workspace on the output for this seat
	struct sway_container *ws = seat_get_focus_inactive(seat, output->swayc);
	if (ws && ws->type != C_WORKSPACE) {
		ws = container_parent(ws, C_WORKSPACE);
	}
	if (!ws) {
		return output->swayc;
	}

	if ((*surface = layer_surface_at(output,
				&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
				ox, oy, sx, sy))) {
		return ws;
	}
	if (ws->sway_workspace->fullscreen) {
		return tiling_container_at(ws->sway_workspace->fullscreen, lx, ly,
				surface, sx, sy);
	}
	if ((*surface = layer_surface_at(output,
				&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
				ox, oy, sx, sy))) {
		return ws;
	}

	struct sway_container *c;
	if ((c = container_at(ws, lx, ly, surface, sx, sy))) {
		return c;
	}

	if ((*surface = layer_surface_at(output,
				&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
				ox, oy, sx, sy))) {
		return ws;
	}
	if ((*surface = layer_surface_at(output,
				&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
				ox, oy, sx, sy))) {
		return ws;
	}

	c = seat_get_active_child(seat, output->swayc);
	if (c) {
		return c;
	}
	if (!c && output->swayc->children->length) {
		c = output->swayc->children->items[0];
		return c;
	}

	return output->swayc;
}

/**
 * Determine if the edge of the given container is on the edge of the
 * workspace/output.
 */
static bool edge_is_external(struct sway_container *cont, enum wlr_edges edge) {
	enum sway_container_layout layout = L_NONE;
	switch (edge) {
	case WLR_EDGE_TOP:
	case WLR_EDGE_BOTTOM:
		layout = L_VERT;
		break;
	case WLR_EDGE_LEFT:
	case WLR_EDGE_RIGHT:
		layout = L_HORIZ;
		break;
	case WLR_EDGE_NONE:
		sway_assert(false, "Never reached");
		return false;
	}

	// Iterate the parents until we find one with the layout we want,
	// then check if the child has siblings between it and the edge.
	while (cont->type != C_OUTPUT) {
		if (cont->parent->layout == layout) {
			int index = list_find(cont->parent->children, cont);
			if (index > 0 && (edge == WLR_EDGE_LEFT || edge == WLR_EDGE_TOP)) {
				return false;
			}
			if (index < cont->parent->children->length - 1 &&
					(edge == WLR_EDGE_RIGHT || edge == WLR_EDGE_BOTTOM)) {
				return false;
			}
		}
		cont = cont->parent;
	}
	return true;
}

static enum wlr_edges find_edge(struct sway_container *cont,
		struct sway_cursor *cursor) {
	if (cont->type != C_VIEW) {
		return WLR_EDGE_NONE;
	}
	struct sway_view *view = cont->sway_view;
	if (view->border == B_NONE || !view->border_thickness || view->using_csd) {
		return WLR_EDGE_NONE;
	}

	enum wlr_edges edge = 0;
	if (cursor->cursor->x < cont->x + view->border_thickness) {
		edge |= WLR_EDGE_LEFT;
	}
	if (cursor->cursor->y < cont->y + view->border_thickness) {
		edge |= WLR_EDGE_TOP;
	}
	if (cursor->cursor->x >= cont->x + cont->width - view->border_thickness) {
		edge |= WLR_EDGE_RIGHT;
	}
	if (cursor->cursor->y >= cont->y + cont->height - view->border_thickness) {
		edge |= WLR_EDGE_BOTTOM;
	}

	return edge;
}

/**
 * If the cursor is over a _resizable_ edge, return the edge.
 * Edges that can't be resized are edges of the workspace.
 */
static enum wlr_edges find_resize_edge(struct sway_container *cont,
		struct sway_cursor *cursor) {
	enum wlr_edges edge = find_edge(cont, cursor);
	if (edge && !container_is_floating(cont) && edge_is_external(cont, edge)) {
		return WLR_EDGE_NONE;
	}
	return edge;
}

static void handle_down_motion(struct sway_seat *seat,
		struct sway_cursor *cursor, uint32_t time_msec) {
	struct sway_container *con = seat->op_container;
	if (seat_is_input_allowed(seat, con->sway_view->surface)) {
		double moved_x = cursor->cursor->x - seat->op_ref_lx;
		double moved_y = cursor->cursor->y - seat->op_ref_ly;
		double sx = seat->op_ref_con_lx + moved_x;
		double sy = seat->op_ref_con_ly + moved_y;
		wlr_seat_pointer_notify_motion(seat->wlr_seat, time_msec, sx, sy);
	}
	seat->op_moved = true;
}

static void handle_move_motion(struct sway_seat *seat,
		struct sway_cursor *cursor) {
	struct sway_container *con = seat->op_container;
	desktop_damage_whole_container(con);
	container_floating_translate(con,
			cursor->cursor->x - cursor->previous.x,
			cursor->cursor->y - cursor->previous.y);
	desktop_damage_whole_container(con);
}

static void calculate_floating_constraints(struct sway_container *con,
		int *min_width, int *max_width, int *min_height, int *max_height) {
	if (config->floating_minimum_width == -1) { // no minimum
		*min_width = 0;
	} else if (config->floating_minimum_width == 0) { // automatic
		*min_width = 75;
	} else {
		*min_width = config->floating_minimum_width;
	}

	if (config->floating_minimum_height == -1) { // no minimum
		*min_height = 0;
	} else if (config->floating_minimum_height == 0) { // automatic
		*min_height = 50;
	} else {
		*min_height = config->floating_minimum_height;
	}

	if (config->floating_maximum_width == -1) { // no maximum
		*max_width = INT_MAX;
	} else if (config->floating_maximum_width == 0) { // automatic
		struct sway_container *ws = container_parent(con, C_WORKSPACE);
		*max_width = ws->width;
	} else {
		*max_width = config->floating_maximum_width;
	}

	if (config->floating_maximum_height == -1) { // no maximum
		*max_height = INT_MAX;
	} else if (config->floating_maximum_height == 0) { // automatic
		struct sway_container *ws = container_parent(con, C_WORKSPACE);
		*max_height = ws->height;
	} else {
		*max_height = config->floating_maximum_height;
	}
}

static void handle_resize_floating_motion(struct sway_seat *seat,
		struct sway_cursor *cursor) {
	struct sway_container *con = seat->op_container;
	enum wlr_edges edge = seat->op_resize_edge;

	// The amount the mouse has moved since the start of the resize operation
	// Positive is down/right
	double mouse_move_x = cursor->cursor->x - seat->op_ref_lx;
	double mouse_move_y = cursor->cursor->y - seat->op_ref_ly;

	if (edge == WLR_EDGE_TOP || edge == WLR_EDGE_BOTTOM) {
		mouse_move_x = 0;
	}
	if (edge == WLR_EDGE_LEFT || edge == WLR_EDGE_RIGHT) {
		mouse_move_y = 0;
	}

	double grow_width = edge & WLR_EDGE_LEFT ? -mouse_move_x : mouse_move_x;
	double grow_height = edge & WLR_EDGE_TOP ? -mouse_move_y : mouse_move_y;

	if (seat->op_resize_preserve_ratio) {
		double x_multiplier = grow_width / seat->op_ref_width;
		double y_multiplier = grow_height / seat->op_ref_height;
		double max_multiplier = fmax(x_multiplier, y_multiplier);
		grow_width = seat->op_ref_width * max_multiplier;
		grow_height = seat->op_ref_height * max_multiplier;
	}

	// Determine new width/height, and accommodate for floating min/max values
	double width = seat->op_ref_width + grow_width;
	double height = seat->op_ref_height + grow_height;
	int min_width, max_width, min_height, max_height;
	calculate_floating_constraints(con, &min_width, &max_width,
			&min_height, &max_height);
	width = fmax(min_width, fmin(width, max_width));
	height = fmax(min_height, fmin(height, max_height));

	// Apply the view's min/max size
	if (con->type == C_VIEW) {
		double view_min_width, view_max_width, view_min_height, view_max_height;
		view_get_constraints(con->sway_view, &view_min_width, &view_max_width,
				&view_min_height, &view_max_height);
		width = fmax(view_min_width, fmin(width, view_max_width));
		height = fmax(view_min_height, fmin(height, view_max_height));
	}

	// Recalculate these, in case we hit a min/max limit
	grow_width = width - seat->op_ref_width;
	grow_height = height - seat->op_ref_height;

	// Determine grow x/y values - these are relative to the container's x/y at
	// the start of the resize operation.
	double grow_x = 0, grow_y = 0;
	if (edge & WLR_EDGE_LEFT) {
		grow_x = -grow_width;
	} else if (edge & WLR_EDGE_RIGHT) {
		grow_x = 0;
	} else {
		grow_x = -grow_width / 2;
	}
	if (edge & WLR_EDGE_TOP) {
		grow_y = -grow_height;
	} else if (edge & WLR_EDGE_BOTTOM) {
		grow_y = 0;
	} else {
		grow_y = -grow_height / 2;
	}

	// Determine the amounts we need to bump everything relative to the current
	// size.
	int relative_grow_width = width - con->width;
	int relative_grow_height = height - con->height;
	int relative_grow_x = (seat->op_ref_con_lx + grow_x) - con->x;
	int relative_grow_y = (seat->op_ref_con_ly + grow_y) - con->y;

	// Actually resize stuff
	con->x += relative_grow_x;
	con->y += relative_grow_y;
	con->width += relative_grow_width;
	con->height += relative_grow_height;

	if (con->type == C_VIEW) {
		struct sway_view *view = con->sway_view;
		view->x += relative_grow_x;
		view->y += relative_grow_y;
		view->width += relative_grow_width;
		view->height += relative_grow_height;
	}

	arrange_windows(con);
}

static void handle_resize_tiling_motion(struct sway_seat *seat,
		struct sway_cursor *cursor) {
	int amount_x = 0;
	int amount_y = 0;
	int moved_x = cursor->cursor->x - seat->op_ref_lx;
	int moved_y = cursor->cursor->y - seat->op_ref_ly;
	enum wlr_edges edge_x = WLR_EDGE_NONE;
	enum wlr_edges edge_y = WLR_EDGE_NONE;
	struct sway_container *con = seat->op_container;

	if (seat->op_resize_edge & WLR_EDGE_TOP) {
		amount_y = (seat->op_ref_height - moved_y) - con->height;
		edge_y = WLR_EDGE_TOP;
	} else if (seat->op_resize_edge & WLR_EDGE_BOTTOM) {
		amount_y = (seat->op_ref_height + moved_y) - con->height;
		edge_y = WLR_EDGE_BOTTOM;
	}
	if (seat->op_resize_edge & WLR_EDGE_LEFT) {
		amount_x = (seat->op_ref_width - moved_x) - con->width;
		edge_x = WLR_EDGE_LEFT;
	} else if (seat->op_resize_edge & WLR_EDGE_RIGHT) {
		amount_x = (seat->op_ref_width + moved_x) - con->width;
		edge_x = WLR_EDGE_RIGHT;
	}

	if (amount_x != 0) {
		container_resize_tiled(seat->op_container, edge_x, amount_x);
	}
	if (amount_y != 0) {
		container_resize_tiled(seat->op_container, edge_y, amount_y);
	}
}

void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
		bool allow_refocusing) {
	if (time_msec == 0) {
		time_msec = get_current_time_msec();
	}

	struct sway_seat *seat = cursor->seat;

	if (seat->operation != OP_NONE) {
		switch (seat->operation) {
		case OP_DOWN:
			handle_down_motion(seat, cursor, time_msec);
			break;
		case OP_MOVE:
			handle_move_motion(seat, cursor);
			break;
		case OP_RESIZE_FLOATING:
			handle_resize_floating_motion(seat, cursor);
			break;
		case OP_RESIZE_TILING:
			handle_resize_tiling_motion(seat, cursor);
			break;
		case OP_NONE:
			break;
		}
		cursor->previous.x = cursor->cursor->x;
		cursor->previous.y = cursor->cursor->y;
		return;
	}

	struct wlr_seat *wlr_seat = seat->wlr_seat;
	struct wlr_surface *surface = NULL;
	double sx, sy;

	// Find the container beneath the pointer's previous position
	struct sway_container *prev_c = container_at_coords(seat,
			cursor->previous.x, cursor->previous.y, &surface, &sx, &sy);
	// Update the stored previous position
	cursor->previous.x = cursor->cursor->x;
	cursor->previous.y = cursor->cursor->y;

	struct sway_container *c = container_at_coords(seat,
			cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
	if (c && config->focus_follows_mouse && allow_refocusing) {
		struct sway_container *focus = seat_get_focus(seat);
		if (focus && c->type == C_WORKSPACE) {
			// Only follow the mouse if it would move to a new output
			// Otherwise we'll focus the workspace, which is probably wrong
			if (focus->type != C_OUTPUT) {
				focus = container_parent(focus, C_OUTPUT);
			}
			struct sway_container *output = c;
			if (output->type != C_OUTPUT) {
				output = container_parent(c, C_OUTPUT);
			}
			if (output != focus) {
				seat_set_focus_warp(seat, c, false, true);
			}
		} else if (c->type == C_VIEW) {
			// Focus c if the following are true:
			// - cursor is over a new view, i.e. entered a new window; and
			// - the new view is visible, i.e. not hidden in a stack or tab; and
			// - the seat does not have a keyboard grab
			if (!wlr_seat_keyboard_has_grab(cursor->seat->wlr_seat) &&
					c != prev_c &&
					view_is_visible(c->sway_view)) {
				seat_set_focus_warp(seat, c, false, true);
			} else {
				struct sway_container *next_focus =
					seat_get_focus_inactive(seat, &root_container);
				if (next_focus && next_focus->type == C_VIEW &&
						view_is_visible(next_focus->sway_view)) {
					seat_set_focus_warp(seat, next_focus, false, true);
				}
			}
		}
	}

	// Handle cursor image
	if (surface) {
		// Reset cursor if switching between clients
		struct wl_client *client = wl_resource_get_client(surface->resource);
		if (client != cursor->image_client) {
			cursor_set_image(cursor, "left_ptr", client);
		}
	} else if (c) {
		// Try a container's resize edge
		enum wlr_edges edge = find_resize_edge(c, cursor);
		if (edge == WLR_EDGE_NONE) {
			cursor_set_image(cursor, "left_ptr", NULL);
		} else if (container_is_floating(c)) {
			cursor_set_image(cursor, wlr_xcursor_get_resize_name(edge), NULL);
		} else {
			if (edge & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT)) {
				cursor_set_image(cursor, "col-resize", NULL);
			} else {
				cursor_set_image(cursor, "row-resize", NULL);
			}
		}
	} else {
		cursor_set_image(cursor, "left_ptr", NULL);
	}

	// send pointer enter/leave
	if (surface != NULL) {
		if (seat_is_input_allowed(seat, surface)) {
			wlr_seat_pointer_notify_enter(wlr_seat, surface, sx, sy);
			wlr_seat_pointer_notify_motion(wlr_seat, time_msec, sx, sy);
		}
	} else {
		wlr_seat_pointer_clear_focus(wlr_seat);
	}

	struct wlr_drag_icon *wlr_drag_icon;
	wl_list_for_each(wlr_drag_icon, &wlr_seat->drag_icons, link) {
		struct sway_drag_icon *drag_icon = wlr_drag_icon->data;
		drag_icon_update_position(drag_icon);
	}
}

static void handle_cursor_motion(struct wl_listener *listener, void *data) {
	struct sway_cursor *cursor = wl_container_of(listener, cursor, motion);
	wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
	struct wlr_event_pointer_motion *event = data;
	wlr_cursor_move(cursor->cursor, event->device,
		event->delta_x, event->delta_y);
	cursor_send_pointer_motion(cursor, event->time_msec, true);
	transaction_commit_dirty();
}

static void handle_cursor_motion_absolute(
		struct wl_listener *listener, void *data) {
	struct sway_cursor *cursor =
		wl_container_of(listener, cursor, motion_absolute);
	wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
	struct wlr_event_pointer_motion_absolute *event = data;
	wlr_cursor_warp_absolute(cursor->cursor, event->device, event->x, event->y);
	cursor_send_pointer_motion(cursor, event->time_msec, true);
	transaction_commit_dirty();
}

/**
 * Remove a button (and duplicates) to the sorted list of currently pressed buttons
 */
static void state_erase_button(struct sway_cursor *cursor, uint32_t button) {
	size_t j = 0;
	for (size_t i = 0; i < cursor->pressed_button_count; ++i) {
		if (i > j) {
			cursor->pressed_buttons[j] = cursor->pressed_buttons[i];
		}
		if (cursor->pressed_buttons[i] != button) {
			++j;
		}
	}
	while (cursor->pressed_button_count > j) {
		--cursor->pressed_button_count;
		cursor->pressed_buttons[cursor->pressed_button_count] = 0;
	}
}

/**
 * Add a button to the sorted list of currently pressed buttons, if there
 * is space.
 */
static void state_add_button(struct sway_cursor *cursor, uint32_t button) {
	if (cursor->pressed_button_count >= SWAY_CURSOR_PRESSED_BUTTONS_CAP) {
		return;
	}
	size_t i = 0;
	while (i < cursor->pressed_button_count && cursor->pressed_buttons[i] < button) {
		++i;
	}
	size_t j = cursor->pressed_button_count;
	while (j > i) {
		cursor->pressed_buttons[j] = cursor->pressed_buttons[j - 1];
		--j;
	}
	cursor->pressed_buttons[i] = button;
	cursor->pressed_button_count++;
}

/**
 * Return the mouse binding which matches modifier, click location, release,
 * and pressed button state, otherwise return null.
 */
static struct sway_binding* get_active_mouse_binding(const struct sway_cursor *cursor,
		list_t *bindings, uint32_t modifiers, bool release, bool on_titlebar,
				     bool on_border, bool on_content) {
	uint32_t click_region = (on_titlebar ? BINDING_TITLEBAR : 0) |
			(on_border ? BINDING_BORDER : 0) |
			(on_content ? BINDING_CONTENTS : 0);

	for (int i = 0; i < bindings->length; ++i) {
		struct sway_binding *binding = bindings->items[i];
		if (modifiers ^ binding->modifiers ||
				cursor->pressed_button_count != (size_t)binding->keys->length ||
				release != (binding->flags & BINDING_RELEASE) ||
				!(click_region & binding->flags)) {
			continue;
		}

		bool match = true;
		for (size_t j = 0; j < cursor->pressed_button_count; j++) {
			uint32_t key = *(uint32_t *)binding->keys->items[j];
			if (key != cursor->pressed_buttons[j]) {
				match = false;
				break;
			}
		}
		if (!match) {
			continue;
		}

		return binding;
	}
	return NULL;
}

void dispatch_cursor_button(struct sway_cursor *cursor,
		uint32_t time_msec, uint32_t button, enum wlr_button_state state) {
	if (time_msec == 0) {
		time_msec = get_current_time_msec();
	}
	struct sway_seat *seat = cursor->seat;

	// Handle ending seat operation
	if (cursor->seat->operation != OP_NONE &&
			button == cursor->seat->op_button && state == WLR_BUTTON_RELEASED) {
		seat_end_mouse_operation(seat);
		seat_pointer_notify_button(seat, time_msec, button, state);
		return;
	}

	// Determine what's under the cursor
	struct wlr_surface *surface = NULL;
	double sx, sy;
	struct sway_container *cont = container_at_coords(seat,
			cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
	bool is_floating = cont && container_is_floating(cont);
	bool is_floating_or_child = cont && container_is_floating_or_child(cont);
	bool is_fullscreen_or_child = cont && container_is_fullscreen_or_child(cont);
	enum wlr_edges edge = cont ? find_edge(cont, cursor) : WLR_EDGE_NONE;
	enum wlr_edges resize_edge = edge ?
		find_resize_edge(cont, cursor) : WLR_EDGE_NONE;
	bool on_border = edge != WLR_EDGE_NONE;
	bool on_contents = cont && !on_border && surface;
	bool on_titlebar = cont && !on_border && !surface;

	// Handle mouse bindings
	struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat);
	uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;

	struct sway_binding *binding = NULL;
	if (state == WLR_BUTTON_PRESSED) {
		state_add_button(cursor, button);
		binding = get_active_mouse_binding(cursor,
			config->current_mode->mouse_bindings, modifiers, false,
			on_titlebar, on_border, on_contents);
	} else {
		binding = get_active_mouse_binding(cursor,
			config->current_mode->mouse_bindings, modifiers, true,
			on_titlebar, on_border, on_contents);
		state_erase_button(cursor, button);
	}
	if (binding) {
		seat_execute_command(seat, binding);
		return;
	}

	// Handle clicking a layer surface
	if (surface && wlr_surface_is_layer_surface(surface)) {
		struct wlr_layer_surface *layer =
			wlr_layer_surface_from_wlr_surface(surface);
		if (layer->current.keyboard_interactive) {
			seat_set_focus_layer(seat, layer);
		}
		seat_pointer_notify_button(seat, time_msec, button, state);
		return;
	}

	// Handle tiling resize via border
	if (resize_edge && button == BTN_LEFT && state == WLR_BUTTON_PRESSED &&
			!is_floating) {
		seat_set_focus(seat, cont);
		seat_begin_resize_tiling(seat, cont, button, edge);
		return;
	}

	// Handle tiling resize via mod
	bool mod_pressed = keyboard &&
		(wlr_keyboard_get_modifiers(keyboard) & config->floating_mod);
	if (!is_floating_or_child && mod_pressed && state == WLR_BUTTON_PRESSED) {
		uint32_t btn_resize = config->floating_mod_inverse ?
			BTN_LEFT : BTN_RIGHT;
		if (button == btn_resize) {
			edge = 0;
			edge |= cursor->cursor->x > cont->x + cont->width / 2 ?
				WLR_EDGE_RIGHT : WLR_EDGE_LEFT;
			edge |= cursor->cursor->y > cont->y + cont->height / 2 ?
				WLR_EDGE_BOTTOM : WLR_EDGE_TOP;

			const char *image = NULL;
			if (edge == (WLR_EDGE_LEFT | WLR_EDGE_TOP)) {
				image = "nw-resize";
			} else if (edge == (WLR_EDGE_TOP | WLR_EDGE_RIGHT)) {
				image = "ne-resize";
			} else if (edge == (WLR_EDGE_RIGHT | WLR_EDGE_BOTTOM)) {
				image = "se-resize";
			} else if (edge == (WLR_EDGE_BOTTOM | WLR_EDGE_LEFT)) {
				image = "sw-resize";
			}
			cursor_set_image(seat->cursor, image, NULL);
			seat_set_focus(seat, cont);
			seat_begin_resize_tiling(seat, cont, button, edge);
			return;
		}
	}

	// Handle beginning floating move
	if (is_floating_or_child && !is_fullscreen_or_child &&
			state == WLR_BUTTON_PRESSED) {
		uint32_t btn_move = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT;
		if (button == btn_move && state == WLR_BUTTON_PRESSED &&
				(mod_pressed || on_titlebar)) {
			while (cont->parent->type != C_WORKSPACE) {
				cont = cont->parent;
			}
			seat_begin_move(seat, cont, button);
			return;
		}
	}

	// Handle beginning floating resize
	if (is_floating_or_child && !is_fullscreen_or_child &&
			state == WLR_BUTTON_PRESSED) {
		// Via border
		if (button == BTN_LEFT && resize_edge != WLR_EDGE_NONE) {
			seat_begin_resize_floating(seat, cont, button, resize_edge);
			return;
		}

		// Via mod+click
		uint32_t btn_resize = config->floating_mod_inverse ?
			BTN_LEFT : BTN_RIGHT;
		if (mod_pressed && button == btn_resize) {
			struct sway_container *floater = cont;
			while (floater->parent->type != C_WORKSPACE) {
				floater = floater->parent;
			}
			edge = 0;
			edge |= cursor->cursor->x > floater->x + floater->width / 2 ?
				WLR_EDGE_RIGHT : WLR_EDGE_LEFT;
			edge |= cursor->cursor->y > floater->y + floater->height / 2 ?
				WLR_EDGE_BOTTOM : WLR_EDGE_TOP;
			seat_begin_resize_floating(seat, floater, button, edge);
			return;
		}
	}

	// Handle mousedown on a container surface
	if (surface && cont && state == WLR_BUTTON_PRESSED) {
		seat_set_focus(seat, cont);
		seat_pointer_notify_button(seat, time_msec, button, state);
		seat_begin_down(seat, cont, button, sx, sy);
		return;
	}

	// Handle clicking a container surface
	if (cont) {
		seat_set_focus(seat, cont);
		seat_pointer_notify_button(seat, time_msec, button, state);
		return;
	}

	seat_pointer_notify_button(seat, time_msec, button, state);
}

static void handle_cursor_button(struct wl_listener *listener, void *data) {
	struct sway_cursor *cursor = wl_container_of(listener, cursor, button);
	wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
	struct wlr_event_pointer_button *event = data;
	dispatch_cursor_button(cursor,
			event->time_msec, event->button, event->state);
	transaction_commit_dirty();
}

static void handle_cursor_axis(struct wl_listener *listener, void *data) {
	struct sway_cursor *cursor = wl_container_of(listener, cursor, axis);
	wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
	struct wlr_event_pointer_axis *event = data;
	wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec,
		event->orientation, event->delta, event->delta_discrete, event->source);
}

static void handle_touch_down(struct wl_listener *listener, void *data) {
	struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down);
	wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
	struct wlr_event_touch_down *event = data;

	struct sway_seat *seat = cursor->seat;
	struct wlr_seat *wlr_seat = seat->wlr_seat;
	struct wlr_surface *surface = NULL;

	double lx, ly;
	wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device,
			event->x, event->y, &lx, &ly);
	double sx, sy;
	container_at_coords(seat, lx, ly, &surface, &sx, &sy);

	seat->touch_id = event->touch_id;
	seat->touch_x = lx;
	seat->touch_y = ly;

	if (!surface) {
		return;
	}

	// TODO: fall back to cursor simulation if client has not bound to touch
	if (seat_is_input_allowed(seat, surface)) {
		wlr_seat_touch_notify_down(wlr_seat, surface, event->time_msec,
				event->touch_id, sx, sy);
		cursor->image_client = NULL;
		wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0);
	}
}

static void handle_touch_up(struct wl_listener *listener, void *data) {
	struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up);
	wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
	struct wlr_event_touch_up *event = data;
	struct wlr_seat *seat = cursor->seat->wlr_seat;
	// TODO: fall back to cursor simulation if client has not bound to touch
	wlr_seat_touch_notify_up(seat, event->time_msec, event->touch_id);
}

static void handle_touch_motion(struct wl_listener *listener, void *data) {
	struct sway_cursor *cursor =
		wl_container_of(listener, cursor, touch_motion);
	wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
	struct wlr_event_touch_motion *event = data;

	struct sway_seat *seat = cursor->seat;
	struct wlr_seat *wlr_seat = seat->wlr_seat;
	struct wlr_surface *surface = NULL;

	double lx, ly;
	wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device,
			event->x, event->y, &lx, &ly);
	double sx, sy;
	container_at_coords(cursor->seat, lx, ly, &surface, &sx, &sy);

	if (seat->touch_id == event->touch_id) {
		seat->touch_x = lx;
		seat->touch_y = ly;

		struct wlr_drag_icon *wlr_drag_icon;
		wl_list_for_each(wlr_drag_icon, &wlr_seat->drag_icons, link) {
			struct sway_drag_icon *drag_icon = wlr_drag_icon->data;
			drag_icon_update_position(drag_icon);
		}
	}

	if (!surface) {
		return;
	}

	// TODO: fall back to cursor simulation if client has not bound to touch
	if (seat_is_input_allowed(cursor->seat, surface)) {
		wlr_seat_touch_notify_motion(wlr_seat, event->time_msec,
			event->touch_id, sx, sy);
	}
}

static double apply_mapping_from_coord(double low, double high, double value) {
	if (isnan(value)) {
		return value;
	}

	return (value - low) / (high - low);
}

static void apply_mapping_from_region(struct wlr_input_device *device,
		struct input_config_mapped_from_region *region, double *x, double *y) {
	double x1 = region->x1, x2 = region->x2;
	double y1 = region->y1, y2 = region->y2;

	if (region->mm) {
		if (device->width_mm == 0 || device->height_mm == 0) {
			return;
		}
		x1 /= device->width_mm;
		x2 /= device->width_mm;
		y1 /= device->height_mm;
		y2 /= device->height_mm;
	}

	*x = apply_mapping_from_coord(x1, x2, *x);
	*y = apply_mapping_from_coord(y1, y2, *y);
}

static void handle_tool_axis(struct wl_listener *listener, void *data) {
	struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis);
	wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
	struct wlr_event_tablet_tool_axis *event = data;
	struct sway_input_device *input_device = event->device->data;

	double x = NAN, y = NAN;
	if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X)) {
		x = event->x;
	}
	if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) {
		y = event->y;
	}

	struct input_config *ic = input_device_get_config(input_device);
	if (ic != NULL && ic->mapped_from_region != NULL) {
		apply_mapping_from_region(event->device, ic->mapped_from_region, &x, &y);
	}

	wlr_cursor_warp_absolute(cursor->cursor, event->device, x, y);
	cursor_send_pointer_motion(cursor, event->time_msec, true);
	transaction_commit_dirty();
}

static void handle_tool_tip(struct wl_listener *listener, void *data) {
	struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip);
	wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
	struct wlr_event_tablet_tool_tip *event = data;
	dispatch_cursor_button(cursor, event->time_msec,
			BTN_LEFT, event->state == WLR_TABLET_TOOL_TIP_DOWN ?
				WLR_BUTTON_PRESSED : WLR_BUTTON_RELEASED);
	transaction_commit_dirty();
}

static void handle_tool_button(struct wl_listener *listener, void *data) {
	struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_button);
	wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
	struct wlr_event_tablet_tool_button *event = data;
	// TODO: the user may want to configure which tool buttons are mapped to
	// which simulated pointer buttons
	switch (event->state) {
	case WLR_BUTTON_PRESSED:
		if (cursor->tool_buttons == 0) {
			dispatch_cursor_button(cursor,
					event->time_msec, BTN_RIGHT, event->state);
		}
		cursor->tool_buttons++;
		break;
	case WLR_BUTTON_RELEASED:
		if (cursor->tool_buttons == 1) {
			dispatch_cursor_button(cursor,
					event->time_msec, BTN_RIGHT, event->state);
		}
		cursor->tool_buttons--;
		break;
	}
	transaction_commit_dirty();
}

static void handle_request_set_cursor(struct wl_listener *listener,
		void *data) {
	struct sway_cursor *cursor =
		wl_container_of(listener, cursor, request_set_cursor);
	if (cursor->seat->operation != OP_NONE) {
		return;
	}
	struct wlr_seat_pointer_request_set_cursor_event *event = data;

	struct wl_client *focused_client = NULL;
	struct wlr_surface *focused_surface =
		cursor->seat->wlr_seat->pointer_state.focused_surface;
	if (focused_surface != NULL) {
		focused_client = wl_resource_get_client(focused_surface->resource);
	}

	// TODO: check cursor mode
	if (focused_client == NULL ||
			event->seat_client->client != focused_client) {
		wlr_log(WLR_DEBUG, "denying request to set cursor from unfocused client");
		return;
	}

	wlr_cursor_set_surface(cursor->cursor, event->surface, event->hotspot_x,
		event->hotspot_y);
	cursor->image = NULL;
	cursor->image_client = focused_client;
}

void cursor_set_image(struct sway_cursor *cursor, const char *image,
		struct wl_client *client) {
	if (!cursor->image || strcmp(cursor->image, image) != 0) {
		wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, image,
				cursor->cursor);
		cursor->image = image;
	}
	cursor->image_client = client;
}

void sway_cursor_destroy(struct sway_cursor *cursor) {
	if (!cursor) {
		return;
	}

	wlr_xcursor_manager_destroy(cursor->xcursor_manager);
	wlr_cursor_destroy(cursor->cursor);
	free(cursor);
}

struct sway_cursor *sway_cursor_create(struct sway_seat *seat) {
	struct sway_cursor *cursor = calloc(1, sizeof(struct sway_cursor));
	if (!sway_assert(cursor, "could not allocate sway cursor")) {
		return NULL;
	}

	struct wlr_cursor *wlr_cursor = wlr_cursor_create();
	if (!sway_assert(wlr_cursor, "could not allocate wlr cursor")) {
		free(cursor);
		return NULL;
	}

	cursor->previous.x = wlr_cursor->x;
	cursor->previous.y = wlr_cursor->y;

	cursor->seat = seat;
	wlr_cursor_attach_output_layout(wlr_cursor,
		root_container.sway_root->output_layout);

	// input events
	wl_signal_add(&wlr_cursor->events.motion, &cursor->motion);
	cursor->motion.notify = handle_cursor_motion;

	wl_signal_add(&wlr_cursor->events.motion_absolute,
		&cursor->motion_absolute);
	cursor->motion_absolute.notify = handle_cursor_motion_absolute;

	wl_signal_add(&wlr_cursor->events.button, &cursor->button);
	cursor->button.notify = handle_cursor_button;

	wl_signal_add(&wlr_cursor->events.axis, &cursor->axis);
	cursor->axis.notify = handle_cursor_axis;

	wl_signal_add(&wlr_cursor->events.touch_down, &cursor->touch_down);
	cursor->touch_down.notify = handle_touch_down;

	wl_signal_add(&wlr_cursor->events.touch_up, &cursor->touch_up);
	cursor->touch_up.notify = handle_touch_up;

	wl_signal_add(&wlr_cursor->events.touch_motion,
		&cursor->touch_motion);
	cursor->touch_motion.notify = handle_touch_motion;

	// TODO: tablet protocol support
	// Note: We should emulate pointer events for clients that don't support the
	// tablet protocol when the time comes
	wl_signal_add(&wlr_cursor->events.tablet_tool_axis,
		&cursor->tool_axis);
	cursor->tool_axis.notify = handle_tool_axis;

	wl_signal_add(&wlr_cursor->events.tablet_tool_tip, &cursor->tool_tip);
	cursor->tool_tip.notify = handle_tool_tip;

	wl_signal_add(&wlr_cursor->events.tablet_tool_button, &cursor->tool_button);
	cursor->tool_button.notify = handle_tool_button;

	wl_signal_add(&seat->wlr_seat->events.request_set_cursor,
			&cursor->request_set_cursor);
	cursor->request_set_cursor.notify = handle_request_set_cursor;

	cursor->cursor = wlr_cursor;

	return cursor;
}

redpajama_set_name: RedPajamaGithub


text:
Bainbridge Conversation
Bainbridge Conversation Rachel Anne Seymour engages island residents in a conversation about their community.
Marshall: "hp 2 di w/out evr havng wkd thru spdr web"
tristan baurick
Longtime Bainbridge journalist Becky Fox Marshall has revived her regular Bainbridge Islander column. This week, she aims to fight irrelevancy by taking on technology….
"I am proud to say," my friend announced in the midst of a conversation about cell phones, "that I hope to die having never sent a text message."
Wow. If I had to choose one thing I hope to never have done upon my death, I'm not sure I'd select never sending a text message. But he loathes such things.
What I loathe, besides spiders (making this time of year particularly perilous) is becoming irrelevant. I remember as a young person thinking that "old" people were nice and all, but they seemed so, so irrelevant. So disconnected. So … yesterday. Imagine not being able to figure out a TV remote?
That's why I have made a point of getting to know my computer and a variety of applications. Why all my photos are digital and online. Why many of my conversations are via the three IM options resident on my client. Why, I finally took on the iPod and brought music back to my life.
I felt I was keeping up pretty well. I got on Facebook despite the groans from my peers (who since have joined – TOLD YA!). My children gave me accolades for being slightly ahead when graded on a curve with their peers' parents. But with every birthday I feel more pressure to step up my game. After all, my 87-year-old former mother-in-law writes emails (most are annoying sappy forwards, but still – she's tech savvy!) How was I to differentiate myself?
I took on the DVR, that's what I did. In consolidating my telephone, internet and television services to save money, the nice customer service rep crunched some numbers and was excited to tell me that I was saving sooo much money that I could add a DVR and still come out ahead.
Heck yea, let's do it, I told her. I feel behind the times and, dare I say, slightly irrelevant when people tell me how they can pause live TV, record an entire series to watch during a marathon weekend, or go out in the evening and not miss their favorite show.
I was in serious danger of saying, out loud, "Well I remember you just plugged in your television, hooked up a cable and felt pretty damn privileged to have more than four channels to choose from. Why in my parents' day, you actually had to GET UP and cross the room to change the channel! IMAGINE the hardship of that era!"
But I caught myself, and agreed – never realizing that all I really had done was open the door to a whole new level of complexity and frustration. Four thousand channels, eight remotes, two blue lights and three instruction manuals later – it's clearly too much. But I'm not giving up. Either is Comcast. They're sending a fellow to the house AGAIN because after all the phone calls, furniture moving and unplugging and re-connecting, they're stumped, too.
I'm going to master this, even if I never again watch an actual television show or find the time to watch the hours of shows I've recorded. That isn't the point. The point is being able to work it.
When I learn how to make my TV and all its related equipment work, I plan to take on Skype. I'm not up to Twitter or Foursquare level yet, but I hope to get there – I can only imagine the heights of relevancy I surely will experience. I also need to figure out this FTP site I've been struggling with – and what constitutes an XML file and why I want RSS feeds, and the age-old question, "What does Error 404 mean, really?"
Last night I told my friend, "I hope to die without ever having walked through a spider web only to find, an hour later, a giant spider caught in my hair." I texted it to him: "hp 2 di w/out evr havng wkd thru spdr web 2 find, hr ltr, giant spdr cot in hair. LOL. JK." He never responded.
October 4, 2010 OpinionBecky Fox Marshall, columns
← Moran School may dodge the wrecking ball Police blotter: "Oh!" says the burglar →
3 thoughts on "Marshall: "hp 2 di w/out evr havng wkd thru spdr web""
Melanie Olson says:
Oh Becky- stil mkng me laff aftr all these yrs!
Chris Hoag says:
Great article and we'll be there soon to help!
Jon Quitslund says:
Hi Becky, Welcome back! Better than ever. You set a great example; I'm way behind you, using the inertia of age and satisfaction with my familiar distractions as reasons not to adapt. No cable, so no TV; watching DVDs on my laptop, tuning in radio there too. Give me the simple life!
Where do you buy gas on Bainbridge Island?
Suquamish (37%, 13 Votes)
Chevron at Highway 305 and High School Road (26%, 9 Votes)
Chevron off Hildebrand Lane (20%, 7 Votes)
Poulsbo (6%, 2 Votes)
The closest station I can find when I am low on gas. (6%, 2 Votes)
76 in Island Center (3%, 1 Votes)
I bike or take public transportation. (3%, 1 Votes)
Seattle (0%, 0 Votes)
Bainbridge News on Facebook
Mark Coolidge on Work on Wyatt Hill subdivision begins
Mark Coolidge on Slip into a dock fundraiser
Julie on Bainbridge's first retail pot shop opened
Mark Coolidge on Rockaway Beach residents asked to reduce water use
Steve on Bainbridge's first retail pot shop opened
Bainbridge Islander: News about your community
Subscribe to The Bainbridge Conversation
Categories Select Category Agriculture Arts & Entertainment Bainbridge Islander Bainbridge Islander preview BI Front Page Birding Business City Hall Community Courts Downtown economy Environment Ferries Fire Department Food & Drink Friday Preview health History Island Road History Lynwood Center Opinion Parks Police Politics Puget Sound Rolling Bay Schools Social Services Sports transportation Uncategorized Weather
Archives Select Month September 2015 (1) August 2015 (3) July 2015 (4) June 2015 (13) May 2015 (11) April 2015 (14) March 2015 (17) February 2015 (13) January 2015 (23) December 2014 (5) November 2014 (8) October 2014 (6) September 2014 (8) August 2014 (6) July 2014 (18) June 2014 (7) May 2014 (23) April 2014 (13) March 2014 (16) February 2014 (17) January 2014 (3) October 2013 (1) September 2013 (13) August 2013 (12) July 2013 (9) June 2013 (9) May 2013 (16) April 2013 (16) March 2013 (15) February 2013 (15) January 2013 (14) December 2012 (13) November 2012 (16) October 2012 (16) September 2012 (13) August 2012 (9) July 2012 (12) June 2012 (10) May 2012 (5) April 2012 (8) March 2012 (10) February 2012 (10) January 2012 (9) December 2011 (11) November 2011 (13) October 2011 (5) September 2011 (6) August 2011 (8) July 2011 (6) June 2011 (12) May 2011 (12) April 2011 (13) March 2011 (14) February 2011 (16) January 2011 (5) December 2010 (17) November 2010 (10) October 2010 (22) September 2010 (6) August 2010 (12) July 2010 (20) June 2010 (14) May 2010 (24) April 2010 (27) March 2010 (32) February 2010 (24) January 2010 (32) December 2009 (34) November 2009 (31) October 2009 (38) September 2009 (18) August 2009 (24) July 2009 (31) June 2009 (49) May 2009 (43) April 2009 (39) March 2009 (45) February 2009 (53) January 2009 (39) December 2008 (35) November 2008 (32) October 2008 (37) September 2008 (38) August 2008 (33) July 2008 (30) June 2008 (18) May 2008 (40) April 2008 (35) March 2008 (28) February 2008 (24) January 2008 (52) December 2007 (76) November 2007 (91) October 2007 (106) September 2007 (55) August 2007 (95) July 2007 (108) June 2007 (105) May 2007 (95) April 2007 (94) March 2007 (68) February 2007 (87) January 2007 (83) December 2006 (74) November 2006 (94) October 2006 (67) September 2006 (73) August 2006 (95) July 2006 (36) June 2006 (49) May 2006 (53) April 2006 (42) March 2006 (74) February 2006 (2)

redpajama_set_name: RedPajamaCommonCrawl


The regulator said 1st Centennial Bank was closed Friday by the California Department of Financial Institutions. The department appointed the FDIC as receiver of the Redlands lender.
The closing was the third announced this year by the FDIC.
To protect the depositors, the FDIC agreed with First California Bank in Westlake Village to assume the insured deposits of 1st Centennial.
The six branches of 1st Centennial will reopen Monday as branches of First California Bank.
As of Jan. 9, 1st Centennial had total assets of $803.3 million and total deposits of $676.9 million.
Expect this to be a regular occurrence.


text:
Welcome to UK Music Reviews » Home
GIG REVIEW: Kip Moore
Categories:	Gig Reviews
Kip Moore performing his Room To Spare: Acoustic Tour at The Town Hall Birmingham on Wednesday 29th May 2019 Images and Review by Kevin CooperCountry music sensation Kip Moore walked onto the stage at the Town Hall in Birmingham last night and with just a spotlight and a guitar for com ...
GIG REVIEW: Olly Murs
Olly Murs performing his All The Hits Tour at the FlyDSA Arena Sheffield on Friday 24th May 2019 Images and Review by Kevin CooperOlly Murs, the 2009 X Factor runner up and The Voice judge had the crowd of all ages up on their feet from the very first beat when he emerged from within t ...
INTERVIEW: Kian Egan
Categories:	Interviews
Kian Egan, an Irish singer songwriter and member of Westlife, chats with Kevin Cooper about working with Mariah Carey, playing Croke Park Stadium, Westlife's forthcoming album and their current tour of the UK.Kian Egan is an Irish singer and songwriter who is best known as a member of We ...
GIG REVIEW: Michael Bublé
Michael Bublé performing An Evening With Michael Bublé at The Resorts World Arena Birmingham on Tuesday 21st May 2019 Images and Review by Kevin CooperIt was over five years ago when Michael Bublé was last on a stage in Birmingham, and last night saw him perform the second night of ...
GIG REVIEW: Katherine Jenkins
Katherine Jenkins performing her An Audience With Katherine Jenkins Tour at The Royal Concert Hall Nottingham on Friday 17th May 2019 Images and Review by Kevin CooperThe Welsh mezzo-soprano, Katherine Jenkins OBE, was at the Royal Concert Hall last night to celebrate the release of he ...
GIG REVIEW: UB40
UB40 performing their For The Many 40th Anniversary Tour at The Royal Concert Nottingham on Monday 13th May 2019 Images and Review by Kevin CooperUB40 came to the Royal Concert Hall last night and invited everyone to celebrate forty years since they formed as an eight piece band back i ...
INTERVIEW: Bill Bailey
Bill Bailey, an English comedian, musician, singer, actor, TV and radio presenter and author, chats with Kevin Cooper about his favourite comedians, performing at Knebworth, freedom of speech and his latest tour of the UK, Larks In Transit.Bill Bailey is an English comedian, musicia ...
GIG REVIEW: Samantha Fish
Samantha Fish performing at The Stables Milton Keynes on Wednesday 8th May 2019Images and Review by Kevin CooperSamantha Fish was at The Stables in Milton Keynes last night for the second date on her UK tour and showed just what a stunning guitarist she really is.Having been recording ...
GIG REVIEW: Marc Almond
Marc Almond performing at The Royal Concert Hall Nottingham on Monday 6th May 2019Images and Review by Kevin CooperIt is refreshing when an artist embarks upon a tour without the added pressure of having to promote their latest album, but Marc Almond did just that at the Royal Concert ...


Our essentials course for users who need to be able to use and understand EXCEL 2007, this course will teach participants all the advanced features and functions and also show you how 2007 is compatible with later versions.
You get your first look at Excel and all you see are little blocks, rows upon rows and column upon column. You feel something beginning in the pit of your stomach and you remonstrate with yourself: You are sure you have bitten off more than you can chew this time. Stop. Breathe slowly. Relax – it's not half as intimidating as you initially think. Welcome to the workshop on Excel 2007 – Essentials. Excel is a spreadsheet application, this is where you would create, maintain and manage your household budget. In a working environment excel can be used across the board from human resources to accounting and credit control. Excel is used to analyse numbers, keep track of data and present information in a spreadsheet. As this is the Essentials workshop we strongly advise participants to attend the Advanced workshop on Excel 2007 for a fully rounded learning experience. As always, this is a practical workshop where participants will practice what they learn on computers, we also provide learners with a pre workshop review form to enable the trainer to see what functions of excel students are already using and what aspects they wish to learn or know more about. Excel 2007 has a new interface and larger worksheet and workbook sizes. It also has powerful tools to help you format your data into usable information. Some of the objectives of the Essentials workshop are: To differentiate between worksheets, workbooks, rows, columns and cells; enter values and labels; use and copy formulas; learn the basic functions and format text and numbers. If you have used Excel before, you will notice the change in the interface, all the menus and toolbars have been replaced with a ribbon interface, each tab on the ribbon contain selections, commands and features. The screen tip provides information about the selection. A worksheet is a collection of cells, text, data and calculations are entered into these cells. TIP: Choosing the proper format to save your file: Click the Office button and then select Save As. To save in Excel format, choose Excel workshop, if you need the file to be accessible in previous formats, choose Excel 97-2003 Workbook. Use Control + S to quick save and to save as a PDF, add the PDF add-in and save. Our workshop begins with learning how to create a worksheet and enter data. Worksheets are created with a purpose, usually for numbers. Sometimes text is entered and a useful command for text to keep the column alignment is to wrap the text. We take a moment to explain the new format as well. Most of the workshop focuses on building formulas which is the backbone of Excel, we will also teach participants to edit and copy formulas. The next part of the workshop focuses on using the functions of Excel and students will learn the basic Excel functions. We end off our workshop with some time saving tools and formatting.
This course is intended for novice users of Microsoft Excel.


text:
Night Time Stories
Garden City Movement talk "Apollonia", the genreless "Garden City Movement sound", and music scene in Tel Aviv
Jess Bartlet
In a past life as Lorena B, Yoav and Roi performed with Disclosure, Bondax, Blonde, and Apparat to name a few. Johnny, the third member met the two as a music…
Khruangbin talk Con Todo El Mundo, the Friday Morning video, NTS, AirKhruang.com & more [Q&A]
Khruangbin are an exciting nomadic Texan trio made up of musicians; Laura Lee on bass, Mark Speer on guitar and D.J. on drums. Khruangbin's globetrotting antics, and eclectic influences ooze into…
Chaouche releases mesmerising new single "So What" on Night Time Stories
Chaouche is an exciting upcoming Bristol-based musician, and it's not going unnoticed. Chaouche's last single "I" chose by Lauren Laverne to be a lucrative "Headphones Moment" on BBC Radio 6;…


text:
Tourism Push Plays Up 'Only In Minnesota' Getaways
Filed Under:advertising, Campaigns, Gov. Mark Dayton, Minnesota News, Pat Kessler, Susie Jones, Tourism
Deb James send in this pic from Schmitt Lake in Inver Grove Heights, Minn. Send us your pictures!(credit: Deb James)
ST. PAUL, Minn. (WCCO) — Minnesota's making a major new push for tourism dollars with the state's largest-ever advertising campaign to lure vacationers.
The $12 billion tourism industry is already among the fastest growing sectors of Minnesota's economy. And the state's new tourism motto, "Only In Minnesota," tries to capture what's unique: like the Mall of America.
"This is truly a great example of 'Only In Minnesota,'" said Maureen Bausch, the Executive Vice president of the Mall of America. "We might be America's mall, but we belong to Minnesota."
The new push will attempt to lure vacationers as far south as Denver and Kansas City, and as far north as Saskatoon.
The marketing effort will also target younger people through social media on Facebook, Pinterest and Instagram. And on Twitter, the hashtag #OnlyInMinnesota will highlight unique Minnesota outdoor and cultural places and events.
"It's not as much about getting names and addresses to send them a travel guide, it's to get people talking to each other about the unique attractions," John Edman, the Explore Minnesota Tourism Director, said.
Adman says the campaign will feature Minnesota's distinct outdoor adventures, cultural experiences and unique landmarks.
Adman Interview
Edman said more than $11 million in additional funding provided by the Minnesota Legislature has allowed Explore Minnesota to expand its marketing impact. He says for every $1 spent advertising, Minnesota gets $8 back.
The new television ads are already running in 14 states and Canadian provinces.


text:
Speaking His Language: Junior's Spanish Newscast a First for Mason Cable Network
Issmar Ventura at BBC News LA, where he interned in summer 2015. Photo provided.
By Damian Cristodero
Issmar Ventura knows exactly what he wants to do once he lands a job as a journalist.
"I want to cover those things not a lot of people cover," he said. "I want to focus not only on my population but the minority population as a whole. I feel those voices are not heard enough."
For now, though, it is enough that Ventura, a George Mason University junior communications major, gets his own voice heard on Mason Cable Network's first Spanish-language news show, a show he created.
The prerecorded show—Noticiero GMU—is telecast Wednesdays after the 6 p.m. English-language news and features Ventura reading his own copy that includes what he called "my little bit of spice."
"I'm not only going to class, I'm running my own news show. I'm building a team," he said. "I have camera people working now. By next year, I want to have a co-anchor. It's a great opportunity."
It also is a means to an end for Ventura, who in 2000 moved with his family from El Salvador to Woodbridge, Va.
Issmar Venturo and Adriana Rugierro, lead anchor for Noticiero Estrella. Ventura shadowed Rugierro for part of his internship. Provided photo.
Ventura interned last summer in Los Angeles with BBC Mundo, the British Broadcasting Corporation's online Spanish-language platform, for which he mostly did reporting and research. To be in front of the camera, Ventura said he was told he needed practice, polish and a portfolio. The Spanish-language show at George Mason is a start.
"He asked me why I wanted to do it," Ventura said of Robert Horan, Mason Cable Network's general manager, who gave the show the green light. "I said I want to develop my skills, and I'm not going to be able to develop them if I'm just reading and writing. I'm taking the resources the school is offering to build my portfolio."
While Horan, a senior communications major, thought the idea would promote diversity and help Mason Cable Network reach a broader audience, he also liked Ventura's initiative.
"He's really passionate about what he wants to do," Horan said. "He's already trying to find his niche within the school, which is really cool to see."
"His drive to succeed is inspiring," said Brydin Banning, Ventura's academic advisor last year, who is now at the University of Denver.
Ventura puts together his show with news director Kala West, a senior communications major. After deciding on stories, Ventura said he writes copy using news services as sources for national features and his own reporting for campus issues.
Soon, he said, he'd like to do studio interviews focused on minority achievement.
"Let's say I know an alumnus from the Communication Department who is doing it big somewhere," Ventura said. "I want to bring [in] that person because I want that person to share their experience so it can motivate another student."
And add to Ventura's portfolio.


72422B03-I SiC- and Si3N4-based ceramic MEMS sensors are among the few types of high temperature sensors, currently under development, that can be utilized for the direct measurement of pressure and temperature distributions in the combustion chamber of turbine engines or other high temperature environments. SiCN MEMS sensors present excellent mechanical properties, electric stabilities, and processing compatibility, as well as low cost for the high temperature application. This project will develop a SiCN MEMS sensor suite, including pressure and temperature sensors, for high temperature applications. Phase I will evaluate existing high temperature pressure and temperature sensor techniques, investigate SiCN electric properties to 1500¿C, determine the feasibility of fabricating the SiCN sensor, complete the structural design for the sensor, and analyze performance. Commercial Applications and Other Benefits as described by awardee: The SiCN high temperature MEMS sensor suite should provide the ¿in-service¿ data required for experiment and control in high temperature applications, and should be highly desired in the energy, space and military industries for electricity generation, atomic reaction, tubing engine, rocket motor, raw material processing, etc.


Vocals in the style of Allison Krause and Sarah McLaughlin, breathtakingly lush and transcendant, against cool instrumental beds of guitars, piano, strings, percussion.Journey through the beauty of your soul with this phenomenal artist.
Lisbeth Scott is a singer/songwriter/composer whose voice, songs, and music have appeared on over 100 films. Hans Zimmer first discovered how beautifully Scott's haunting voice complimented film in 1995 when a friend brought her in to sing her first solo film session on the movie "Toys". Since then Scott has gone on to work with Hollywood's top composers on literally 100s of films as a singer, songwriter and composer. John Williams, who calls Scott's voice "ravishing", composed a five minute solo for her on Spielberg's "Munich"; her signature voice and songwriting began the Narnia film "The Lion the Witch and the Wardrobe" (score by Harry Gregson Williams) and was also in the sequel Prince Caspian. John Debney featured Lisbeth's voice and writing in the Academy Award Nominated score to Mel Gibson's "The Passion of The Christ."
While her work as a vocalist and songwriter for film was progressing, she began her own music company and released 6 acclaimed CDs on her label Whistling Bird Music, Inc. Her releases "Dove" and "Fair Skye" were named album of the year by New Age Reporter. She then co-founded the duo "Biomusique" with percussionist and film scorer Greg Ellis and released their debut "The Ten Thousand Steps" on Kosmic Music in 2008. It's currently nominated for best vocals, new artist and album of the year by New Age Reporter. Scott contributed additional music to Ellis's score to the powerful documentary "The Road To Falluja" in 2008. She also co-scored the HBO film "Ithuteng" with John Debney and has contributed countless songs to top films and television shows, most recently HBO's "True Blood" for which she co-wrote a feature song with composer Nathan Barr. Her song "Real Love" performed by Macy Gray for the Tony Scott film "Domino", became a cult classic. Scott also co-penned the end title song "Good To Me" for the 20th Century Fox release "Shutter" .
The unique character of Lisbeth's voice and style has matched her up with several top recording artists including the EMI European sensation "Bliss" with whom she co-wrote 3 tunes to be included on their April 2009 release. Her work with RCA's Paul Schwartz on State of Grace I and II graced Billboard's top ten for ten weeks.
Scott began her musical career as a child, studying piano performance at the New England Conservatory. She went on to continue her studies at The University of London and Connecticut College . Always fascinated with the marriage of film and music, she created several of her own short films as a teen, for which she wrote the scores.
After school, she picked up guitar, harmonium, and several other instruments, put together her own recording studio and immediately moved to Los Angeles to follow her path. Her love affair with film and film music continues to this day. She currently resides in Venice, California.


text:
Santissima Annunziata – appellativo cristiano usati per indicare Maria, madre di Gesù, con particolare riferimento al momento dell'Annunciazione da parte dell'Arcangelo Gabriele
 Ordine Supremo della Santissima Annunziata – onorificenza sabauda
 Oratorio della Santissima Annunziata – chiesa di Ferrara
Santissima Annunziata – rione del comune di Messina

Pagine correlate
 Chiesa della Santissima Annunziata
 Basilica della Santissima Annunziata (disambigua)

redpajama_set_name: RedPajamaWikipedia


text:
"Tagging" Along on the Phnom Penh Graffiti Tour
Two inspiring young Cambodian artists take us on a vibrant tour of graffiti in the capital.
What's On Phnom Penh joins local graffiti artists-enthusiasts Koy and Davido on a brand new tour, giving a unique glimpse into Phnom Penh's secret street art hotspots.
By day, 19-year old Phnom Penh natives David Myers (Davido) and Kimchean Koy (Koy) are architecture students at the prestigious American University of Phnom Penh by day. By night, they are up-and-coming graffiti artists, scaling buildings throughout lakeside and collaborating with street artists from across the globe.
Now, having finished their exams, the duo have launched a brand new Sunday morning graffiti tour of Phnom Penh, taking small groups on a journey through the capital's hidden pockets of street art, and offering an introduction to the city's modern art as a whole.
"What I love about street art is how it always changes. Nothing is permanent."
The tour begins at 9am on Sunday Morning (don't panic, you can always head there straight from Pontoon…) at the National Museum, where Koy and Davido have prearranged tuk-tuks for our small group of graffiti tour guinea pigs. From here, we're told, the graffiti tour will take us to notable graffiti spots as well as established galleries like Sa Sa Bassac, Kbach Gallery, Java Arts and Nowhere art studio. As the boys see it, for Phnom Penh's creative crowd, the only distinction between "street art" and the more conventional variety is the location – and with so few dedicated galleries in Phnom Penh, some of the best work is delivered out on the street.
Of course, the bittersweet thing about art in public spaces is that it lacks permanence. Like many other places around the world, Graffiti in Phnom Penh is often covered by the authorities or painted over or developed in an unplanned collaboration with other artists. While this can be frustrating, it's also what makes it special.
"What I love about street art is how it always changes. Nothing is permanent," says Koy.
In the tuk-tuk to our first stop, Myers and Koy talk us through the general art scene in the city. Far from the archetypal cliche of a feckless teenage graffiti artists, these boys are true connoisseurs – thoughtful and eloquent about the styles and techniques, and deeply respectful of the communities whose spaces we visit.
What's more, as active street artists themselves, Koy and Myers are well and truly involved in the scene, with an encyclopedic knowledge of where to find work by every famous artist and and up-to-date information on every twist, turn and trend. It's clear that this tour is a living, breathing journey that will evolve each week as new pieces spring up – or are painted over.
"This tour is a living, breathing journey that will evolve each week as new pieces spring up – or are painted over."
The first stop in our tour (which changes on a weekly basis) takes us to an easy-to-miss piece on the side of a residential apartment complex in Tonle Bassac, where the duo instantly start to explain the subtle nuances of spray-can technique. It's clear these guys really know their stuff.
Davido also takes the opportunity to squash one of the more damaging misconceptions about street art in the city. He explains that artists typically ask the building owners or residents if they can paint on the walls – permission usually granted, if it adds some interest or beauty to often-unloved buildings – and rarely experience pushback from the authorities.
One famous exception, of course, is US artist David Choe's giant mural of a seamstress (and resident of the building), painted on the side of the iconic White Building. Choe spent 8 hours a day for a full week completing the striking, impressive mural, but following a mix-up over permissions, it was painted over by city authorities. The white paint wasn't thick enough to completely crush Choe's efforts, though.
"Come and have a look at it when it's been raining," Koy says with a twinkle in his eye. "The artwork shines right through the paint."
… Some of the city's hidden secrets, it seems, are buried deeper than others.
While the new perspective on the city creates a whole new level of appreciation for Phnom Penh, it's our supremely likable teenage tour guides that really make the trip.
It's not just their vast knowledge of all things related to art and Phnom Penh, but also their incredible work ethic (Koy explains they often operate on 3 hours sleep) and focus on social responsibility.
Koy and Davido starting the tour with the noble aim of bringing Phnom Penh's artistic and creative elements to the surface, and to engage their fellow Cambodians in particular with the art right under their noses. Despite the effort and time the boys are putting into this endeavour, they aren't pocketing any of the cash, either. Instead, the profits will go to the NGOs Braveheart and the Cambodian Children's Fund.
The pair also want to encourage more children to take up art as a tool of communication. Art is not usually taught in school in Cambodia, and where it is taught, it's more about mastering specific techniques than expressing new ideas. As Davido explains, some of the profits will go "towards funding free tours for children who wouldn't have the chance to experience it."
"Some of the profits will go towards funding free tours for children who wouldn't have the chance to experience it."
Even for art-lover Davido, the traditional Khmer art scene felt too restrictive to offer many models of inspiration. For him, he says, it was Western abstract artists like Picasso that he admired the most in his formative years.
It hasn't always been this way. Art played a vital role in Cambodia's history, and was a core part of the curriculum in schools prior to the Khmer Rouge. But the artistic ecosystem has been slow to recover – and, short of formal canvases and exhibitions, young Cambodian artists increasingly use street art to experiment with new ideas.
In fact, it's at the bohemian enclave of Boeung Kak "Lake" (the area still known as Lakeside, despite the lake itself being filled in several years ago), that the tour really comes alive. Davido explains that many people feel uncomfortable in this area, as it's seen as "sketchy" – plagued with extreme poverty and drug addiction. As so often happens, the social deprivation created the conditions for the grassroots art scene to flourish.
"As so often happens, the social deprivation created the conditions for the grassroots art scene to flourish."
Here, you can see an amazing array of pieces by street artists from around the world. Work from internationally acclaimed artists like Seth Globepainter and Alias 2.0 abounds, incorporating Khmer style nagas and other classic design elements with personal style and cultural references, splashed high across the sides of tenement blocks and crumbling houses. There are some incredible pieces here, including designs on the side of an orphanage, created in collaboration with the local community.
From rough and ready lakeside, it's back to hipster central: a huge collaboration by Khmer and global street artists on St. 240 1/2, near ARTillery Cafe and La Familia. This vivid collection is a complete change of tone from the gritty underground feel of lakeside – the legacy of a major street art festival last year.
We finish up at the skate shop near Independence Monument, where the boys proudly show off a fitting piece of their own – a striking portrait of Ros Sereysothea, pop queen of Cambodia's golden age, rendered in contemporary style.
In just a couple of hours, we're left feeling that we've seen the city in a completely new light, the contrasting locations and styles telling a story of an underground creative movement that's steadily gaining ground.
What's more, the weekday versions of the tour will take visitors to the city's first graffiti gallery (unfortunately, closed on our Sunday visit). It seems that this generation of Khmer artists are ready to come in from the cold and start making permanent pieces, too.
Want to book a tour? Drop Kimchean Koy or David Myers a message through Facebook!
Pingback: In the Endless Jungle of Phnom Penh – WHAT'S ON PHNOM PENH
More in Features & Interviews
By Amanda Kaufmann July 9, 2019
It's only been in the country for a decade, but Cambodia's rock climbers are already competing...
By Frazer MacRobert June 14, 2019
Beer, glorious beer. There's a new kid on the block sweeping it's way across Phnom Penh...
By Amanda Kaufmann June 7, 2019
By Mark Tilly March 30, 2019
Looking back on the life of the legendary journalist.
Street Art from Paris to Phnom Penh: We Chat to Alias 2.0.
Max Mason: DJ Tuk Tuk


What a fun weekend. I hope you spoiled and pampered all the mothers in your life for Mother's Day! As we are getting closer to the summer, we are planning out our vacations and my kiddos are getting so excited. Today, a few of my friends and I thought we'd get the ball rolling for you so we got together with Get Away Today to give one lucky winner….
Sounds amazing, right? Raise your hand if you'd like to win this vacation for your family!! Lucky for you – today you have the chance!
Get Away Today is our go to travel planning website! They do their best to team up with the top travel destinations to help save families up to 40% off their vacation packages! Places such as Disneyland Parks, Crusies, San Diego, Mexico, Hawaii, etc!
I need to make sure and highlight the other amazing bloggers that are helping make this giveaway possible! They are all crazy talented and I would love it if you took the time to stop by their websites and say hi!
The giveaway will run from May 11, 2015 at 12:00am to May 19, 2015 at 12:00am!
I recently found your site and I totally love it. Also- what a great giveaway.
What a great giveaway! My family needs a vacation in the worst way. I'd love to win!
This is awesome! That would be amazing to win!!
This IS the ultimate giveaway!
Thanks for the chance!! This would be a true blessing!! My little family is in need of a vacation, and what better place then Disneyland!!!
What a fabulous giveaway! And so good to get familiar with some of these new to me bloggers/mavens.