mirror of
https://github.com/labwc/labwc.git
synced 2026-04-12 08:21:13 -04:00
First attempt at integration with nmouse and keyboard bindings
This commit is contained in:
parent
4b6efb7307
commit
dfd9aa4aba
6 changed files with 294 additions and 1 deletions
|
|
@ -20,4 +20,12 @@ struct wlr_scene_node *lab_wlr_scene_get_prev_node(struct wlr_scene_node *node);
|
|||
/* A variant of wlr_scene_output_commit() that respects wlr_output->pending */
|
||||
bool lab_wlr_scene_output_commit(struct wlr_scene_output *scene_output);
|
||||
|
||||
enum magnify_dir {
|
||||
MAGNIFY_INCREASE,
|
||||
MAGNIFY_DECREASE
|
||||
};
|
||||
|
||||
void magnify_toggle (void);
|
||||
void magnify_set_scale (enum magnify_dir dir);
|
||||
|
||||
#endif /* LABWC_SCENE_HELPERS_H */
|
||||
|
|
|
|||
|
|
@ -134,6 +134,9 @@ static struct key_combos {
|
|||
.name = "command",
|
||||
.value = "brightnessctl set 10%-",
|
||||
},
|
||||
}, {
|
||||
.binding = "C-A-m",
|
||||
.action = "ToggleMagnify",
|
||||
}, {
|
||||
.binding = NULL,
|
||||
},
|
||||
|
|
@ -441,6 +444,24 @@ static struct mouse_combos {
|
|||
.button = "Middle",
|
||||
.event = "Press",
|
||||
.action = "Raise",
|
||||
}, {
|
||||
.context = "All",
|
||||
.button = "W-Up",
|
||||
.event = "Scroll",
|
||||
.action = "SetMagnification",
|
||||
.attributes[0] = {
|
||||
.name = "scale",
|
||||
.value = "up",
|
||||
},
|
||||
}, {
|
||||
.context = "All",
|
||||
.button = "W-Down",
|
||||
.event = "Scroll",
|
||||
.action = "SetMagnification",
|
||||
.attributes[0] = {
|
||||
.name = "scale",
|
||||
.value = "down",
|
||||
},
|
||||
}, {
|
||||
.context = NULL,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -60,6 +60,9 @@ struct rcxml {
|
|||
bool focus_follow_mouse_requires_movement;
|
||||
bool raise_on_focus;
|
||||
|
||||
bool magnify;
|
||||
int magnification;
|
||||
|
||||
/* theme */
|
||||
char *theme_name;
|
||||
int corner_radius;
|
||||
|
|
|
|||
22
src/action.c
22
src/action.c
|
|
@ -13,6 +13,7 @@
|
|||
#include "common/parse-bool.h"
|
||||
#include "common/spawn.h"
|
||||
#include "common/string-helpers.h"
|
||||
#include "common/scene-helpers.h"
|
||||
#include "debug.h"
|
||||
#include "labwc.h"
|
||||
#include "menu/menu.h"
|
||||
|
|
@ -110,6 +111,8 @@ enum action_type {
|
|||
ACTION_TYPE_SHADE,
|
||||
ACTION_TYPE_UNSHADE,
|
||||
ACTION_TYPE_TOGGLE_SHADE,
|
||||
ACTION_TYPE_TOGGLE_MAGNIFY,
|
||||
ACTION_TYPE_SET_MAGNIFICATION
|
||||
};
|
||||
|
||||
const char *action_names[] = {
|
||||
|
|
@ -163,6 +166,8 @@ const char *action_names[] = {
|
|||
"Shade",
|
||||
"Unshade",
|
||||
"ToggleShade",
|
||||
"ToggleMagnify",
|
||||
"SetMagnification",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -415,6 +420,12 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char
|
|||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
case ACTION_TYPE_SET_MAGNIFICATION:
|
||||
if (!strcmp(argument, "scale")) {
|
||||
action_arg_add_str(action, argument, content);
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
wlr_log(WLR_ERROR, "Invalid argument for action %s: '%s'",
|
||||
|
|
@ -1046,6 +1057,17 @@ actions_run(struct view *activator, struct server *server,
|
|||
view_set_shade(view, false);
|
||||
}
|
||||
break;
|
||||
case ACTION_TYPE_TOGGLE_MAGNIFY:
|
||||
magnify_toggle();
|
||||
break;
|
||||
case ACTION_TYPE_SET_MAGNIFICATION:
|
||||
const char *dir = action_get_str(action, "scale", NULL);
|
||||
if (!strcmp(dir, "up")) {
|
||||
magnify_set_scale(MAGNIFY_INCREASE);
|
||||
} else if (!strcmp(dir, "down")) {
|
||||
magnify_set_scale(MAGNIFY_DECREASE);
|
||||
}
|
||||
break;
|
||||
case ACTION_TYPE_INVALID:
|
||||
wlr_log(WLR_ERROR, "Not executing unknown action");
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,12 @@
|
|||
#include <wlr/types/wlr_scene.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "common/scene-helpers.h"
|
||||
#include "labwc.h"
|
||||
|
||||
#include <wlr/render/pass.h>
|
||||
#include <wlr/types/wlr_buffer.h>
|
||||
#include <wlr/render/drm_format_set.h>
|
||||
#include "common/macros.h"
|
||||
|
||||
struct wlr_surface *
|
||||
lab_wlr_surface_from_node(struct wlr_scene_node *node)
|
||||
|
|
@ -34,6 +40,218 @@ lab_wlr_scene_get_prev_node(struct wlr_scene_node *node)
|
|||
return prev;
|
||||
}
|
||||
|
||||
|
||||
/* TODO: move to rc. (or theme?) settings */
|
||||
#define magnifier_border 1 /* in pixels */
|
||||
#define magnifier_crop_size 100 /* how many pixels in each direction of the cursor */
|
||||
|
||||
static void
|
||||
magnify(struct output *output, struct wlr_buffer *output_buffer, struct wlr_box *damage)
|
||||
{
|
||||
/* Reuse a single scratch buffer */
|
||||
static struct wlr_buffer *tmp_buffer = NULL;
|
||||
static struct wlr_texture *tmp_texture = NULL;
|
||||
|
||||
/* TODO: This looks way too complicated to just get the used format */
|
||||
struct wlr_drm_format wlr_drm_format = {0};
|
||||
struct wlr_shm_attributes shm_attribs = {0};
|
||||
struct wlr_dmabuf_attributes dma_attribs = {0};
|
||||
if (wlr_buffer_get_dmabuf(output_buffer, &dma_attribs)) {
|
||||
wlr_drm_format.format = dma_attribs.format;
|
||||
wlr_drm_format.len = 1;
|
||||
wlr_drm_format.modifiers = &dma_attribs.modifier;
|
||||
} else if (wlr_buffer_get_shm(output_buffer, &shm_attribs)) {
|
||||
wlr_drm_format.format = shm_attribs.format;
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "Failed to read buffer format");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fetch scale-adjusted cursor coordinates */
|
||||
struct server *server = output->server;
|
||||
struct wlr_cursor *cursor = server->seat.cursor;
|
||||
double ox = cursor->x;
|
||||
double oy = cursor->y;
|
||||
wlr_output_layout_output_coords(server->output_layout, output->wlr_output, &ox, &oy);
|
||||
ox *= output->wlr_output->scale;
|
||||
oy *= output->wlr_output->scale;
|
||||
|
||||
/* TODO: refactor, to use rc. settings */
|
||||
int width = magnifier_crop_size * 2 + 1;
|
||||
int height = width;
|
||||
double x = ox - magnifier_crop_size;
|
||||
double y = oy - magnifier_crop_size;
|
||||
double cropped_width = width;
|
||||
double cropped_height = height;
|
||||
double dst_x = 0;
|
||||
double dst_y = 0;
|
||||
|
||||
/* Ensure everything is kept within output boundaries */
|
||||
if (x < 0) {
|
||||
cropped_width += x;
|
||||
dst_x = x * -1;
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0) {
|
||||
cropped_height += y;
|
||||
dst_y = y * -1;
|
||||
y = 0;
|
||||
}
|
||||
cropped_width = MIN(cropped_width, (double)output_buffer->width - x);
|
||||
cropped_height = MIN(cropped_height, (double)output_buffer->height - y);
|
||||
|
||||
/* (Re)create the temporary buffer if required */
|
||||
if (tmp_buffer && (tmp_buffer->width != width || tmp_buffer->height != height)) {
|
||||
wlr_log(WLR_ERROR, "tmp buffer size changed, dropping");
|
||||
assert(tmp_texture);
|
||||
wlr_texture_destroy(tmp_texture);
|
||||
wlr_buffer_drop(tmp_buffer);
|
||||
tmp_buffer = NULL;
|
||||
tmp_texture = NULL;
|
||||
}
|
||||
if (!tmp_buffer) {
|
||||
tmp_buffer = wlr_allocator_create_buffer(
|
||||
server->allocator, width, height, &wlr_drm_format);
|
||||
}
|
||||
if (!tmp_buffer) {
|
||||
wlr_log(WLR_ERROR, "Failed to allocate temporary magnifier buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Extract source region into temporary buffer */
|
||||
|
||||
struct wlr_render_pass *tmp_render_pass = wlr_renderer_begin_buffer_pass(
|
||||
server->renderer, tmp_buffer, NULL);
|
||||
|
||||
/* FIXME, try to re-use the existing output texture instead */
|
||||
wlr_buffer_lock(output_buffer);
|
||||
struct wlr_texture *output_texture = wlr_texture_from_buffer(
|
||||
server->renderer, output_buffer);
|
||||
assert(output_texture);
|
||||
|
||||
struct wlr_render_texture_options opts = {
|
||||
.texture = output_texture,
|
||||
.src_box = (struct wlr_fbox) {
|
||||
x, y, cropped_width, cropped_height },
|
||||
.dst_box = (struct wlr_box) {
|
||||
dst_x, dst_y, cropped_width, cropped_height },
|
||||
.alpha = NULL,
|
||||
};
|
||||
wlr_render_pass_add_texture(tmp_render_pass, &opts);
|
||||
if (!wlr_render_pass_submit(tmp_render_pass)) {
|
||||
wlr_log(WLR_ERROR, "Failed to extract magnifier source region");
|
||||
wlr_texture_destroy(output_texture);
|
||||
goto cleanup;
|
||||
}
|
||||
wlr_texture_destroy(output_texture);
|
||||
|
||||
/* Render to the output buffer itself */
|
||||
tmp_render_pass = wlr_renderer_begin_buffer_pass(
|
||||
server->renderer, output_buffer, NULL);
|
||||
|
||||
/* Borders */
|
||||
struct wlr_box border_box = {
|
||||
.x = ox - (width / 2 + magnifier_border) * rc.magnification,
|
||||
.y = oy - (height / 2 + magnifier_border) * rc.magnification,
|
||||
.width = (width + magnifier_border * 2) * rc.magnification,
|
||||
.height = (height + magnifier_border * 2) * rc.magnification,
|
||||
};
|
||||
struct wlr_render_rect_options bg_opts = {
|
||||
.box = border_box,
|
||||
/* TODO: make this a rc. setting */
|
||||
.color = (struct wlr_render_color) { 1, 0, 0, 1 },
|
||||
.clip = NULL,
|
||||
};
|
||||
wlr_render_pass_add_rect(tmp_render_pass, &bg_opts);
|
||||
|
||||
/* Paste the magnified result back into the output buffer */
|
||||
if (!tmp_texture) {
|
||||
tmp_texture = wlr_texture_from_buffer(server->renderer, tmp_buffer);
|
||||
assert(tmp_texture);
|
||||
}
|
||||
opts = (struct wlr_render_texture_options) {
|
||||
.texture = tmp_texture,
|
||||
.src_box = (struct wlr_fbox) { 0, 0, width, height },
|
||||
.dst_box = (struct wlr_box) {
|
||||
.x = ox - (width / 2) * rc.magnification,
|
||||
.y = oy - (height / 2) * rc.magnification,
|
||||
.width = width * rc.magnification,
|
||||
.height = height * rc.magnification,
|
||||
},
|
||||
.alpha = NULL,
|
||||
.clip = NULL,
|
||||
//.filter_mode = WLR_SCALE_FILTER_NEAREST,
|
||||
.filter_mode = WLR_SCALE_FILTER_BILINEAR,
|
||||
};
|
||||
wlr_render_pass_add_texture(tmp_render_pass, &opts);
|
||||
if (!wlr_render_pass_submit(tmp_render_pass)) {
|
||||
wlr_log(WLR_ERROR, "Failed to submit render pass");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* And finally mark the extra damage */
|
||||
*damage = border_box;
|
||||
damage->width += 1;
|
||||
damage->height += 1;
|
||||
|
||||
cleanup:
|
||||
wlr_buffer_unlock(output_buffer);
|
||||
}
|
||||
|
||||
static bool
|
||||
output_wants_magnification(struct output *output)
|
||||
{
|
||||
static double x = -1;
|
||||
static double y = -1;
|
||||
struct wlr_cursor *cursor = output->server->seat.cursor;
|
||||
if (!rc.magnify) {
|
||||
x = -1;
|
||||
y = -1;
|
||||
return false;
|
||||
}
|
||||
if (cursor->x == x && cursor->y == y) {
|
||||
return false;
|
||||
}
|
||||
x = cursor->x;
|
||||
y = cursor->y;
|
||||
return output_nearest_to_cursor(output->server) == output;
|
||||
}
|
||||
|
||||
/*
|
||||
* Toggles magnification on and off
|
||||
*/
|
||||
|
||||
void magnify_toggle (void)
|
||||
{
|
||||
if (rc.magnify) {
|
||||
rc.magnify = false;
|
||||
} else {
|
||||
rc.magnify = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Increases and decreases magnification scale
|
||||
*/
|
||||
|
||||
void magnify_set_scale (enum magnify_dir dir)
|
||||
{
|
||||
if (dir == MAGNIFY_INCREASE) {
|
||||
if (rc.magnify) {
|
||||
rc.magnification++;
|
||||
} else {
|
||||
rc.magnify = true;
|
||||
rc.magnification = 2;
|
||||
}
|
||||
} else {
|
||||
if (rc.magnify && rc.magnification > 2) {
|
||||
rc.magnification--;
|
||||
} else {
|
||||
rc.magnify = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a copy of wlr_scene_output_commit()
|
||||
* as it doesn't use the pending state at all.
|
||||
|
|
@ -44,16 +262,31 @@ lab_wlr_scene_output_commit(struct wlr_scene_output *scene_output)
|
|||
assert(scene_output);
|
||||
struct wlr_output *wlr_output = scene_output->output;
|
||||
struct wlr_output_state *state = &wlr_output->pending;
|
||||
struct output *output = wlr_output->data;
|
||||
bool wants_magnification = output_wants_magnification(output);
|
||||
static bool last_mag = false;
|
||||
static int last_scale = 2;
|
||||
|
||||
if (!wlr_output->needs_frame && !pixman_region32_not_empty(
|
||||
&scene_output->damage_ring.current)) {
|
||||
&scene_output->damage_ring.current) && !wants_magnification
|
||||
&& last_mag != rc.magnify && last_scale != rc.magnification) {
|
||||
return false;
|
||||
}
|
||||
|
||||
last_mag = rc.magnify;
|
||||
last_scale = rc.magnification;
|
||||
|
||||
if (!wlr_scene_output_build_state(scene_output, state, NULL)) {
|
||||
wlr_log(WLR_ERROR, "Failed to build output state for %s",
|
||||
wlr_output->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
struct wlr_box additional_damage = {0};
|
||||
if (state->buffer && rc.magnify) {
|
||||
magnify(output, state->buffer, &additional_damage);
|
||||
}
|
||||
|
||||
if (!wlr_output_commit(wlr_output)) {
|
||||
wlr_log(WLR_INFO, "Failed to commit output %s",
|
||||
wlr_output->name);
|
||||
|
|
@ -66,5 +299,9 @@ lab_wlr_scene_output_commit(struct wlr_scene_output *scene_output)
|
|||
* again.
|
||||
*/
|
||||
wlr_damage_ring_rotate(&scene_output->damage_ring);
|
||||
|
||||
if (!wlr_box_empty(&additional_damage)) {
|
||||
wlr_damage_ring_add_box(&scene_output->damage_ring, &additional_damage);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1206,6 +1206,8 @@ rcxml_init(void)
|
|||
rc.focus_follow_mouse = false;
|
||||
rc.focus_follow_mouse_requires_movement = true;
|
||||
rc.raise_on_focus = false;
|
||||
rc.magnify = false;
|
||||
rc.magnification = 2;
|
||||
|
||||
rc.doubleclick_time = 500;
|
||||
rc.scroll_factor = 1.0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue