mirror of
https://github.com/labwc/labwc.git
synced 2026-06-13 14:33:18 -04:00
rebase send-shortcut
This commit is contained in:
commit
13a487fb35
24 changed files with 256 additions and 44 deletions
|
|
@ -217,9 +217,9 @@ If you have not created an rc.xml config file, default bindings will be:
|
|||
| `super`-`mouse-right` | resize window
|
||||
| `super`-`arrow` | resize window to fill half the output
|
||||
| `alt`-`space` | show the window menu
|
||||
| `XF86AudioLowerVolume` | amixer sset Master 5%-
|
||||
| `XF86AudioRaiseVolume` | amixer sset Master 5%+
|
||||
| `XF86AudioMute` | amixer sset Master toggle
|
||||
| `XF86AudioLowerVolume` | pactl set-sink-volume @DEFAULT_SINK@ -5%
|
||||
| `XF86AudioRaiseVolume` | pactl set-sink-volume @DEFAULT_SINK@ +5%
|
||||
| `XF86AudioMute` | pactl set-sink-mute @DEFAULT_SINK@ toggle
|
||||
| `XF86MonBrightnessUp` | brightnessctl set +10%
|
||||
| `XF86MonBrightnessDown` | brightnessctl set 10%-
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ struct conf {
|
|||
uint32_t button_text;
|
||||
uint32_t button_background;
|
||||
uint32_t details_background;
|
||||
uint32_t details_border_color;
|
||||
uint32_t background;
|
||||
uint32_t text;
|
||||
uint32_t button_border;
|
||||
|
|
@ -60,6 +61,7 @@ struct conf {
|
|||
ssize_t button_gap_close;
|
||||
ssize_t button_margin_right;
|
||||
ssize_t button_padding;
|
||||
ssize_t details_margin;
|
||||
};
|
||||
|
||||
struct pointer {
|
||||
|
|
@ -300,10 +302,10 @@ render_details_scroll_button(cairo_t *cairo, struct nag *nag,
|
|||
get_text_size(cairo, nag->conf->font_description, &text_width,
|
||||
&text_height, NULL, 1, true, "%s", button->text);
|
||||
|
||||
int border = nag->conf->button_border_thickness;
|
||||
int padding = nag->conf->button_padding;
|
||||
int border = nag->conf->details_border_thickness;
|
||||
int padding = (nag->conf->button_padding / 3) + 2;
|
||||
|
||||
cairo_set_source_u32(cairo, nag->conf->details_background);
|
||||
cairo_set_source_u32(cairo, nag->conf->details_border_color);
|
||||
cairo_rectangle(cairo, button->x, button->y,
|
||||
button->width, button->height);
|
||||
cairo_fill(cairo);
|
||||
|
|
@ -316,7 +318,7 @@ render_details_scroll_button(cairo_t *cairo, struct nag *nag,
|
|||
|
||||
cairo_set_source_u32(cairo, nag->conf->button_text);
|
||||
cairo_move_to(cairo, button->x + border + padding,
|
||||
button->y + border + (button->height - text_height) / 2);
|
||||
button->y + (button->height - text_height) / 2);
|
||||
render_text(cairo, nag->conf->font_description, 1, true,
|
||||
"%s", button->text);
|
||||
}
|
||||
|
|
@ -331,8 +333,8 @@ get_detailed_scroll_button_width(cairo_t *cairo, struct nag *nag)
|
|||
NULL, 1, true, "%s", nag->details.button_down.text);
|
||||
|
||||
int text_width = up_width > down_width ? up_width : down_width;
|
||||
int border = nag->conf->button_border_thickness;
|
||||
int padding = nag->conf->button_padding;
|
||||
int border = nag->conf->details_border_thickness;
|
||||
int padding = (nag->conf->button_padding / 3) + 2;
|
||||
|
||||
return text_width + border * 2 + padding * 2;
|
||||
}
|
||||
|
|
@ -343,8 +345,9 @@ render_detailed(cairo_t *cairo, struct nag *nag, uint32_t y)
|
|||
uint32_t width = nag->width;
|
||||
|
||||
int border = nag->conf->details_border_thickness;
|
||||
int margin = nag->conf->details_margin;
|
||||
int padding = nag->conf->message_padding;
|
||||
int decor = padding + border;
|
||||
int decor = margin + border;
|
||||
|
||||
nag->details.x = decor;
|
||||
nag->details.y = y + decor;
|
||||
|
|
@ -372,7 +375,7 @@ render_detailed(cairo_t *cairo, struct nag *nag, uint32_t y)
|
|||
bool show_buttons = nag->details.offset > 0;
|
||||
int button_width = get_detailed_scroll_button_width(cairo, nag);
|
||||
if (show_buttons) {
|
||||
nag->details.width -= button_width;
|
||||
nag->details.width += border - button_width;
|
||||
pango_layout_set_width(layout,
|
||||
(nag->details.width - padding * 2) * PANGO_SCALE);
|
||||
}
|
||||
|
|
@ -385,7 +388,7 @@ render_detailed(cairo_t *cairo, struct nag *nag, uint32_t y)
|
|||
|
||||
if (!show_buttons) {
|
||||
show_buttons = true;
|
||||
nag->details.width -= button_width;
|
||||
nag->details.width += border - button_width;
|
||||
pango_layout_set_width(layout,
|
||||
(nag->details.width - padding * 2) * PANGO_SCALE);
|
||||
}
|
||||
|
|
@ -401,21 +404,29 @@ render_detailed(cairo_t *cairo, struct nag *nag, uint32_t y)
|
|||
|
||||
nag->details.visible_lines = pango_layout_get_line_count(layout);
|
||||
|
||||
int border_rect_height = nag->details.height + 2 * border;
|
||||
|
||||
if (show_buttons) {
|
||||
nag->details.button_up.x = nag->details.x + nag->details.width;
|
||||
nag->details.button_up.y = nag->details.y;
|
||||
nag->details.button_up.y = nag->details.y - border;
|
||||
nag->details.button_up.width = button_width;
|
||||
nag->details.button_up.height = nag->details.height / 2;
|
||||
nag->details.button_up.height = (border_rect_height + border) / 2;
|
||||
render_details_scroll_button(cairo, nag, &nag->details.button_up);
|
||||
|
||||
nag->details.button_down.x = nag->details.x + nag->details.width;
|
||||
nag->details.button_down.y =
|
||||
nag->details.button_up.y + nag->details.button_up.height;
|
||||
nag->details.button_up.y + nag->details.button_up.height - border;
|
||||
nag->details.button_down.width = button_width;
|
||||
nag->details.button_down.height = nag->details.height / 2;
|
||||
nag->details.button_down.height =
|
||||
border_rect_height - nag->details.button_up.height + border;
|
||||
render_details_scroll_button(cairo, nag, &nag->details.button_down);
|
||||
}
|
||||
|
||||
cairo_set_source_u32(cairo, nag->conf->details_border_color);
|
||||
cairo_rectangle(cairo, margin, nag->details.y - border,
|
||||
nag->details.width + 2 * border, border_rect_height);
|
||||
cairo_fill(cairo);
|
||||
|
||||
cairo_set_source_u32(cairo, nag->conf->details_background);
|
||||
cairo_rectangle(cairo, nag->details.x, nag->details.y,
|
||||
nag->details.width, nag->details.height);
|
||||
|
|
@ -447,7 +458,7 @@ render_button(cairo_t *cairo, struct nag *nag, struct button *button,
|
|||
}
|
||||
|
||||
button->x = *x - border - text_width - padding * 2 + 1;
|
||||
button->y = (int)(ideal_height - text_height) / 2 - padding + 1;
|
||||
button->y = (int)(ideal_height - text_height) / 2 - padding;
|
||||
button->width = text_width + padding * 2;
|
||||
button->height = text_height + padding * 2;
|
||||
|
||||
|
|
@ -1464,14 +1475,16 @@ conf_init(struct conf *conf)
|
|||
conf->keyboard_focus = ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE;
|
||||
conf->bar_border_thickness = 2;
|
||||
conf->message_padding = 8;
|
||||
conf->details_border_thickness = 3;
|
||||
conf->button_border_thickness = 3;
|
||||
conf->button_gap = 20;
|
||||
conf->button_gap_close = 15;
|
||||
conf->button_margin_right = 2;
|
||||
conf->button_padding = 3;
|
||||
conf->button_background = 0x680A0AFF;
|
||||
conf->details_margin = 11;
|
||||
conf->details_border_thickness = 3;
|
||||
conf->details_background = 0x680A0AFF;
|
||||
conf->details_border_color = 0x680A0AFF;
|
||||
conf->background = 0x900000FF;
|
||||
conf->text = 0xFFFFFFFF;
|
||||
conf->button_text = 0xFFFFFFFF;
|
||||
|
|
@ -1551,16 +1564,18 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
|||
TO_COLOR_BORDER_BOTTOM,
|
||||
TO_COLOR_BUTTON_BG,
|
||||
TO_COLOR_DETAILS,
|
||||
TO_COLOR_DETAILS_BORDER,
|
||||
TO_COLOR_TEXT,
|
||||
TO_COLOR_BUTTON_TEXT,
|
||||
TO_THICK_BAR_BORDER,
|
||||
TO_PADDING_MESSAGE,
|
||||
TO_THICK_DET_BORDER,
|
||||
TO_THICK_DETAILS_BORDER,
|
||||
TO_THICK_BTN_BORDER,
|
||||
TO_GAP_BTN,
|
||||
TO_GAP_BTN_DISMISS,
|
||||
TO_MARGIN_BTN_RIGHT,
|
||||
TO_PADDING_BTN,
|
||||
TO_MARGIN_DETAILS,
|
||||
};
|
||||
|
||||
static const struct option opts[] = {
|
||||
|
|
@ -1587,8 +1602,10 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
|||
{"button-text-color", required_argument, NULL, TO_COLOR_BUTTON_TEXT},
|
||||
{"border-bottom-size", required_argument, NULL, TO_THICK_BAR_BORDER},
|
||||
{"message-padding", required_argument, NULL, TO_PADDING_MESSAGE},
|
||||
{"details-border-size", required_argument, NULL, TO_THICK_DET_BORDER},
|
||||
{"details-border-size", required_argument, NULL, TO_THICK_DETAILS_BORDER},
|
||||
{"details-background-color", required_argument, NULL, TO_COLOR_DETAILS},
|
||||
{"details-border-color", required_argument, NULL, TO_COLOR_DETAILS_BORDER},
|
||||
{"details-margin", required_argument, NULL, TO_MARGIN_DETAILS},
|
||||
{"button-border-size", required_argument, NULL, TO_THICK_BTN_BORDER},
|
||||
{"button-gap", required_argument, NULL, TO_GAP_BTN},
|
||||
{"button-dismiss-gap", required_argument, NULL, TO_GAP_BTN_DISMISS},
|
||||
|
|
@ -1633,6 +1650,9 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
|||
" --details-border-size size Thickness for the details border.\n"
|
||||
" --details-background-color RRGGBB[AA]\n"
|
||||
" Details background color.\n"
|
||||
" --details-border-color RRGGBB[AA]\n"
|
||||
" Details border color.\n"
|
||||
" --details-margin margin Margin for the details.\n"
|
||||
" --button-border-size size Thickness for the button border.\n"
|
||||
" --button-gap gap Size of the gap between buttons\n"
|
||||
" --button-dismiss-gap gap Size of the gap for dismiss button.\n"
|
||||
|
|
@ -1769,6 +1789,11 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
|||
fprintf(stderr, "Invalid details background color: %s\n", optarg);
|
||||
}
|
||||
break;
|
||||
case TO_COLOR_DETAILS_BORDER:
|
||||
if (!parse_color(optarg, &conf->details_border_color)) {
|
||||
fprintf(stderr, "Invalid details border color: %s\n", optarg);
|
||||
}
|
||||
break;
|
||||
case TO_COLOR_TEXT: /* Text color */
|
||||
if (!parse_color(optarg, &conf->text)) {
|
||||
fprintf(stderr, "Invalid text color: %s\n", optarg);
|
||||
|
|
@ -1785,7 +1810,7 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
|||
case TO_PADDING_MESSAGE: /* Message padding */
|
||||
conf->message_padding = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case TO_THICK_DET_BORDER: /* Details border thickness */
|
||||
case TO_THICK_DETAILS_BORDER: /* Details border thickness */
|
||||
conf->details_border_thickness = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case TO_THICK_BTN_BORDER: /* Button border thickness */
|
||||
|
|
@ -1803,6 +1828,9 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
|||
case TO_PADDING_BTN: /* Padding for the button text */
|
||||
conf->button_padding = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case TO_MARGIN_DETAILS:
|
||||
conf->details_margin = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
default: /* Help or unknown flag */
|
||||
fprintf(c == 'h' ? stdout : stderr, "%s", usage);
|
||||
return LAB_EXIT_FAILURE;
|
||||
|
|
|
|||
6
data/labwc-session.target
Normal file
6
data/labwc-session.target
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[Unit]
|
||||
Description=labwc session
|
||||
Documentation=man:labwc(1) man:systemd.special(7)
|
||||
BindsTo=graphical-session.target
|
||||
Wants=graphical-session-pre.target
|
||||
After=graphical-session-pre.target
|
||||
|
|
@ -1,5 +1,13 @@
|
|||
# Example autostart file
|
||||
|
||||
# When running under systemd, uncomment the systemctl line below to pull in
|
||||
# graphical-session.target via labwc-session.target. This lets systemd user
|
||||
# services declaring WantedBy=graphical-session.target (panels, portals,
|
||||
# notification daemons, etc.) start in sync with the labwc session. Enable
|
||||
# individual services with: systemctl --user enable <unit>
|
||||
#
|
||||
# systemctl --user --no-block start labwc-session.target
|
||||
|
||||
# Set background color.
|
||||
swaybg -c '#113344' >/dev/null 2>&1 &
|
||||
|
||||
|
|
|
|||
|
|
@ -95,6 +95,12 @@ _labnag_ [options...]
|
|||
*--details-border-size* <size>
|
||||
Set the thickness for the details border.
|
||||
|
||||
*--details-border-color* <RRGGBB[AA]>
|
||||
Set the color of the details border.
|
||||
|
||||
*--details-margin* <margin>
|
||||
Set the margin for the details.
|
||||
|
||||
*--button-border-size* <size>
|
||||
Set the thickness for the button border.
|
||||
|
||||
|
|
|
|||
|
|
@ -514,7 +514,7 @@ Actions that execute other actions. Used in keyboard/mouse bindings.
|
|||
"right-occupied" directions will not wrap.
|
||||
|
||||
*tiled* [up|right|down|left|up-left|up-right|down-left|down-right|center|any]
|
||||
Whether the client is tiled (snapped) along the the
|
||||
Whether the client is tiled (snapped) along the
|
||||
indicated screen edge.
|
||||
|
||||
*tiled_region*
|
||||
|
|
|
|||
|
|
@ -493,6 +493,13 @@ this is for compatibility with Openbox.
|
|||
*<focus><raiseOnFocus>* [yes|no]
|
||||
Raise window to top when focused. Default is no.
|
||||
|
||||
*<focus><raiseOnFocusDelay>* [milliseconds]
|
||||
When raiseOnFocus is enabled, delay the actual raise by this many
|
||||
milliseconds. Default is 0 (raise immediately). A subsequent focus
|
||||
change before the timer elapses restarts or cancels the pending raise.
|
||||
Useful together with followMouse to avoid brief passes of the cursor
|
||||
stacking up z-order changes.
|
||||
|
||||
## WINDOW SNAPPING
|
||||
|
||||
Windows may be "snapped" to an edge or user-defined region of an output when
|
||||
|
|
@ -851,7 +858,7 @@ overrideInhibition="">*
|
|||
A-Space - show window menu
|
||||
```
|
||||
|
||||
Audio and MonBrightness keys are also bound to amixer and
|
||||
Audio and MonBrightness keys are also bound to pactl and
|
||||
brightnessctl, respectively.
|
||||
|
||||
*<keyboard><repeatRate>*
|
||||
|
|
@ -1140,6 +1147,7 @@ Note: To rotate touch events with output rotation, use the libinput
|
|||
<disableWhileTyping></disableWhileTyping>
|
||||
<clickMethod></clickMethod>
|
||||
<scrollMethod></scrollMethod>
|
||||
<scrollButton></scrollButton>
|
||||
<sendEventsMode></sendEventsMode>
|
||||
<calibrationMatrix></calibrationMatrix>
|
||||
<scrollFactor>1.0</scrollFactor>
|
||||
|
|
@ -1244,19 +1252,24 @@ Note: To rotate touch events with output rotation, use the libinput
|
|||
|
||||
The default method depends on the touchpad hardware.
|
||||
|
||||
*<libinput><device><scrollMethod>* [none|twofinger|edge]
|
||||
Configure the method by which physical movements on a touchpad are
|
||||
mapped to scroll events.
|
||||
*<libinput><device><scrollMethod>* [none|twofinger|edge|onbutton]
|
||||
Configure the method by which physical movements are mapped to scroll events.
|
||||
|
||||
The scroll methods available are:
|
||||
- *twofinger* - Scroll by two fingers being placed on the surface of the
|
||||
touchpad, then moving those fingers vertically or horizontally.
|
||||
- *edge* - Scroll by moving a single finger along the right edge
|
||||
(vertical scroll) or bottom edge (horizontal scroll).
|
||||
- *onbutton* - Scroll by pressing a button.
|
||||
- *none* - No scroll events will be produced.
|
||||
|
||||
The default method depends on the touchpad hardware.
|
||||
|
||||
*<libinput><device><scrollButton>* [button]
|
||||
Set the button used for the *onbutton* scroll method.
|
||||
|
||||
*button* is the decimal form of a value from `linux/input-event-codes.h`.
|
||||
|
||||
*<libinput><device><sendEventsMode>* [yes|no|disabledOnExternalMouse]
|
||||
Optionally enable or disable sending any device events.
|
||||
|
||||
|
|
|
|||
|
|
@ -118,6 +118,25 @@ this is accomplished by setting the session variables to empty strings. For
|
|||
systemd, the command `systemctl --user unset-environment` will be invoked to
|
||||
actually remove the variables from the activation environment.
|
||||
|
||||
A systemd user unit named `labwc-session.target` is also shipped alongside
|
||||
the compositor for users who want to integrate labwc with systemd. It binds
|
||||
to the standard `graphical-session.target`, so systemd user services can
|
||||
start and stop in sync with the labwc session when they declare a WantedBy
|
||||
or PartOf relationship to that target. Labwc does not activate the target
|
||||
itself; users opt in by adding lines like the following to their
|
||||
*autostart* and *shutdown* files:
|
||||
|
||||
```
|
||||
systemctl --user --no-block start labwc-session.target
|
||||
systemctl --user stop graphical-session.target
|
||||
```
|
||||
|
||||
The example *autostart* and *shutdown* files shipped with labwc include
|
||||
these commented out. To have a user service automatically started with
|
||||
the session, enable it so the corresponding symlink under the
|
||||
graphical-session.target.wants directory exists, for example by running
|
||||
"systemctl --user enable dms.service".
|
||||
|
||||
# ENVIRONMENT VARIABLES
|
||||
|
||||
Set the environment variables listed below to enable specific debug options.
|
||||
|
|
|
|||
|
|
@ -158,6 +158,8 @@
|
|||
<followMouse>no</followMouse>
|
||||
<followMouseRequiresMovement>yes</followMouseRequiresMovement>
|
||||
<raiseOnFocus>no</raiseOnFocus>
|
||||
<!-- Delay (ms) before applying raise-on-focus. 0 = immediate. -->
|
||||
<raiseOnFocusDelay>0</raiseOnFocusDelay>
|
||||
</focus>
|
||||
|
||||
<snapping>
|
||||
|
|
@ -292,13 +294,13 @@
|
|||
<action name="ShowMenu" menu="client-menu" atCursor="no" />
|
||||
</keybind>
|
||||
<keybind key="XF86AudioLowerVolume">
|
||||
<action name="Execute" command="amixer sset Master 5%-" />
|
||||
<action name="Execute" command="pactl set-sink-volume @DEFAULT_SINK@ -5%" />
|
||||
</keybind>
|
||||
<keybind key="XF86AudioRaiseVolume">
|
||||
<action name="Execute" command="amixer sset Master 5%+" />
|
||||
<action name="Execute" command="pactl set-sink-volume @DEFAULT_SINK@ +5%" />
|
||||
</keybind>
|
||||
<keybind key="XF86AudioMute">
|
||||
<action name="Execute" command="amixer sset Master toggle" />
|
||||
<action name="Execute" command="pactl set-sink-mute @DEFAULT_SINK@ toggle" />
|
||||
</keybind>
|
||||
<keybind key="XF86MonBrightnessUp">
|
||||
<action name="Execute" command="brightnessctl set +10%" />
|
||||
|
|
@ -592,7 +594,7 @@
|
|||
- accelProfile [flat|adaptive]
|
||||
- tapButtonMap [lrm|lmr]
|
||||
- clickMethod [none|buttonAreas|clickfinger]
|
||||
- scrollMethod [twoFinger|edge|none]
|
||||
- scrollMethod [twoFinger|edge|onbutton|none]
|
||||
- sendEventsMode [yes|no|disabledOnExternalMouse]
|
||||
- calibrationMatrix [six float values split by space]
|
||||
- scrollFactor [float]
|
||||
|
|
@ -618,6 +620,7 @@
|
|||
<!-- <disableWhileTyping>yes</disableWhileTyping> -->
|
||||
<!-- <clickMethod>buttonAreas</clickMethod> -->
|
||||
<!-- <scrollMethod>twofinger</scrollMethod> -->
|
||||
<!-- <scrollButton>274</scrollButton> -->
|
||||
<!-- <sendEventsMode>yes</sendEventsMode> -->
|
||||
<!-- <calibrationMatrix>1 0 0 0 1 0</calibrationMatrix> -->
|
||||
<scrollFactor>1.0</scrollFactor>
|
||||
|
|
|
|||
|
|
@ -3,3 +3,11 @@
|
|||
# This file is executed as a shell script when labwc is preparing to terminate
|
||||
# itself.
|
||||
# For further details see labwc-config(5).
|
||||
|
||||
# When running under systemd, uncomment the systemctl line below to tear down
|
||||
# graphical-session.target (which cascades to labwc-session.target via
|
||||
# BindsTo, and to any service declaring PartOf=graphical-session.target).
|
||||
# Running synchronously here ensures those services are stopped before the
|
||||
# Wayland socket goes away, avoiding "Broken pipe" failures on teardown.
|
||||
#
|
||||
# systemctl --user stop graphical-session.target
|
||||
|
|
|
|||
|
|
@ -88,21 +88,21 @@ static struct key_combos {
|
|||
.action = "Execute",
|
||||
.attributes[0] = {
|
||||
.name = "command",
|
||||
.value = "amixer sset Master 5%-",
|
||||
.value = "pactl set-sink-volume @DEFAULT_SINK@ -5%",
|
||||
},
|
||||
}, {
|
||||
.binding = "XF86AudioRaiseVolume",
|
||||
.action = "Execute",
|
||||
.attributes[0] = {
|
||||
.name = "command",
|
||||
.value = "amixer sset Master 5%+",
|
||||
.value = "pactl set-sink-volume @DEFAULT_SINK@ +5%",
|
||||
},
|
||||
}, {
|
||||
.binding = "XF86AudioMute",
|
||||
.action = "Execute",
|
||||
.attributes[0] = {
|
||||
.name = "command",
|
||||
.value = "amixer sset Master toggle",
|
||||
.value = "pactl set-sink-mute @DEFAULT_SINK@ toggle",
|
||||
},
|
||||
}, {
|
||||
.binding = "XF86MonBrightnessUp",
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ struct libinput_category {
|
|||
int dwt; /* -1 or libinput_config_dwt_state */
|
||||
int click_method; /* -1 or libinput_config_click_method */
|
||||
int scroll_method; /* -1 or libinput_config_scroll_method */
|
||||
int scroll_button; /* -1 or a button from linux/input_event_codes.h */
|
||||
int send_events_mode; /* -1 or libinput_config_send_events_mode */
|
||||
bool have_calibration_matrix;
|
||||
double scroll_factor;
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ struct rcxml {
|
|||
bool focus_follow_mouse;
|
||||
bool focus_follow_mouse_requires_movement;
|
||||
bool raise_on_focus;
|
||||
uint32_t raise_on_focus_delay_ms;
|
||||
|
||||
/* theme */
|
||||
char *theme_name;
|
||||
|
|
|
|||
|
|
@ -150,6 +150,11 @@ struct seat {
|
|||
struct server {
|
||||
struct wl_display *wl_display;
|
||||
struct wl_event_loop *wl_event_loop; /* Can be used for timer events */
|
||||
|
||||
/* Pending auto-raise timer (used when rc.raise_on_focus_delay_ms > 0) */
|
||||
struct view *pending_auto_raise_view;
|
||||
struct wl_event_source *pending_auto_raise_timer;
|
||||
|
||||
struct wlr_renderer *renderer;
|
||||
struct wlr_allocator *allocator;
|
||||
struct wlr_backend *backend;
|
||||
|
|
@ -343,6 +348,13 @@ void xdg_shell_finish(void);
|
|||
*/
|
||||
void desktop_focus_view(struct view *view, bool raise);
|
||||
|
||||
/**
|
||||
* desktop_cancel_pending_auto_raise() - cancel any pending delayed auto-raise
|
||||
* (from raiseOnFocusDelay). Called when a view is being destroyed, on config
|
||||
* reload, or when a new focus change with raise=false supersedes the pending.
|
||||
*/
|
||||
void desktop_cancel_pending_auto_raise(void);
|
||||
|
||||
/**
|
||||
* desktop_focus_view_or_surface() - like desktop_focus_view() but can
|
||||
* also focus other (e.g. xwayland-unmanaged) surfaces
|
||||
|
|
|
|||
11
meson.build
11
meson.build
|
|
@ -211,6 +211,17 @@ install_data('data/labwc.desktop', install_dir: get_option('datadir') / 'wayland
|
|||
|
||||
install_data('data/labwc-portals.conf', install_dir: get_option('datadir') / 'xdg-desktop-portal')
|
||||
|
||||
# Install labwc-session.target so that systemd user services with
|
||||
# WantedBy=graphical-session.target can be started and stopped in sync
|
||||
# with a labwc session (see labwc(1) SESSION MANAGEMENT for the opt-in
|
||||
# autostart/shutdown snippet).
|
||||
systemd_feat = get_option('systemd-session')
|
||||
systemd = dependency('systemd', required: systemd_feat)
|
||||
if systemd.found()
|
||||
install_data('data/labwc-session.target',
|
||||
install_dir: systemd.get_variable('systemduserunitdir'))
|
||||
endif
|
||||
|
||||
icons = ['labwc-symbolic.svg', 'labwc.svg']
|
||||
foreach icon : icons
|
||||
icon_path = join_paths('data', icon)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ option('svg', type: 'feature', value: 'enabled', description: 'Enable svg window
|
|||
option('icon', type: 'feature', value: 'enabled', description: 'Enable window icons')
|
||||
option('labnag', type: 'feature', value: 'auto', description: 'Build labnag notification daemon')
|
||||
option('nls', type: 'feature', value: 'auto', description: 'Enable native language support')
|
||||
option('systemd-session', type: 'feature', value: 'auto', description: 'Install labwc-session.target systemd user unit')
|
||||
option('static_analyzer', type: 'feature', value: 'disabled', description: 'Run gcc static analyzer')
|
||||
option('test', type: 'feature', value: 'disabled', description: 'Run tests')
|
||||
option('sections', type: 'feature', value: 'disabled', description: 'Show unused functions')
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ libinput_category_init(struct libinput_category *l)
|
|||
l->dwt = -1;
|
||||
l->click_method = -1;
|
||||
l->scroll_method = -1;
|
||||
l->scroll_button = -1;
|
||||
l->send_events_mode = -1;
|
||||
l->have_calibration_matrix = false;
|
||||
l->scroll_factor = 1.0;
|
||||
|
|
|
|||
|
|
@ -893,9 +893,19 @@ fill_libinput_category(xmlNode *node)
|
|||
} else if (!strcasecmp(content, "twofinger")) {
|
||||
category->scroll_method =
|
||||
LIBINPUT_CONFIG_SCROLL_2FG;
|
||||
} else if (!strcasecmp(content, "onbutton")) {
|
||||
category->scroll_method =
|
||||
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "invalid scrollMethod");
|
||||
}
|
||||
} else if (!strcasecmp(key, "scrollButton")) {
|
||||
int button = atoi(content);
|
||||
if (button != 0) {
|
||||
category->scroll_button = button;
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "invalid scrollButton");
|
||||
}
|
||||
} else if (!strcasecmp(key, "sendEventsMode")) {
|
||||
category->send_events_mode =
|
||||
get_send_events_mode(content);
|
||||
|
|
@ -1187,6 +1197,9 @@ entry(xmlNode *node, char *nodename, char *content)
|
|||
set_bool(content, &rc.focus_follow_mouse_requires_movement);
|
||||
} else if (!strcasecmp(nodename, "raiseOnFocus.focus")) {
|
||||
set_bool(content, &rc.raise_on_focus);
|
||||
} else if (!strcasecmp(nodename, "raiseOnFocusDelay.focus")) {
|
||||
long val = strtol(content, NULL, 10);
|
||||
rc.raise_on_focus_delay_ms = val > 0 ? (uint32_t)val : 0;
|
||||
} else if (!strcasecmp(nodename, "doubleClickTime.mouse")) {
|
||||
long doubleclick_time_parsed = strtol(content, NULL, 10);
|
||||
if (doubleclick_time_parsed > 0) {
|
||||
|
|
@ -1522,6 +1535,7 @@ rcxml_init(void)
|
|||
rc.focus_follow_mouse = false;
|
||||
rc.focus_follow_mouse_requires_movement = true;
|
||||
rc.raise_on_focus = false;
|
||||
rc.raise_on_focus_delay_ms = 0;
|
||||
|
||||
rc.doubleclick_time = 500;
|
||||
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ cycle_begin(enum lab_cycle_dir direction,
|
|||
|
||||
struct view *active_view = server.active_view;
|
||||
if (active_view && active_view->cycle_link.next) {
|
||||
/* Select the active view it's in the cycle list */
|
||||
/* Select the active view if it's in the cycle list */
|
||||
server.cycle.selected_view = active_view;
|
||||
} else {
|
||||
/* Otherwise, select the first view in the cycle list */
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <wlr/types/wlr_subcompositor.h>
|
||||
#include <wlr/types/wlr_xdg_shell.h>
|
||||
#include "common/scene-helpers.h"
|
||||
#include "config/rcxml.h"
|
||||
#include "dnd.h"
|
||||
#include "labwc.h"
|
||||
#include "layers.h"
|
||||
|
|
@ -65,8 +66,51 @@ set_or_offer_focus(struct view *view)
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
handle_auto_raise_timer(void *data)
|
||||
{
|
||||
(void)data;
|
||||
struct view *view = server.pending_auto_raise_view;
|
||||
server.pending_auto_raise_view = NULL;
|
||||
|
||||
if (view && view->mapped) {
|
||||
view_move_to_front(view);
|
||||
}
|
||||
return 0; /* ignored per wl_event_loop docs */
|
||||
}
|
||||
|
||||
void
|
||||
desktop_focus_view(struct view *view, bool raise)
|
||||
desktop_cancel_pending_auto_raise(void)
|
||||
{
|
||||
server.pending_auto_raise_view = NULL;
|
||||
if (server.pending_auto_raise_timer) {
|
||||
/* Disarm by setting to 0 ms */
|
||||
wl_event_source_timer_update(server.pending_auto_raise_timer, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
schedule_delayed_auto_raise(struct view *view)
|
||||
{
|
||||
server.pending_auto_raise_view = view;
|
||||
if (!server.pending_auto_raise_timer) {
|
||||
server.pending_auto_raise_timer =
|
||||
wl_event_loop_add_timer(server.wl_event_loop,
|
||||
handle_auto_raise_timer, NULL);
|
||||
}
|
||||
wl_event_source_timer_update(server.pending_auto_raise_timer,
|
||||
rc.raise_on_focus_delay_ms);
|
||||
}
|
||||
|
||||
/*
|
||||
* The raise_on_focus_delay is only meant to dampen z-order churn from
|
||||
* focus-follows-mouse cursor passes. Explicit focus changes (alt-tab,
|
||||
* Focus action, xdg/xwayland activation, etc.) should raise immediately.
|
||||
* allow_delay is therefore only set when the caller is the sloppy-focus
|
||||
* path in desktop_focus_view_or_surface().
|
||||
*/
|
||||
static void
|
||||
desktop_focus_view_internal(struct view *view, bool raise, bool allow_delay)
|
||||
{
|
||||
assert(view);
|
||||
/*
|
||||
|
|
@ -103,8 +147,17 @@ desktop_focus_view(struct view *view, bool raise)
|
|||
workspaces_switch_to(view->workspace, /*update_focus*/ false);
|
||||
}
|
||||
|
||||
/*
|
||||
* A new focus change supersedes any pending auto-raise from a
|
||||
* previous focus event, regardless of whether we raise now.
|
||||
*/
|
||||
desktop_cancel_pending_auto_raise();
|
||||
if (raise) {
|
||||
view_move_to_front(view);
|
||||
if (allow_delay && rc.raise_on_focus_delay_ms > 0) {
|
||||
schedule_delayed_auto_raise(view);
|
||||
} else {
|
||||
view_move_to_front(view);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -118,6 +171,12 @@ desktop_focus_view(struct view *view, bool raise)
|
|||
show_desktop_reset();
|
||||
}
|
||||
|
||||
void
|
||||
desktop_focus_view(struct view *view, bool raise)
|
||||
{
|
||||
desktop_focus_view_internal(view, raise, /*allow_delay*/ false);
|
||||
}
|
||||
|
||||
/* TODO: focus layer-shell surfaces also? */
|
||||
void
|
||||
desktop_focus_view_or_surface(struct seat *seat, struct view *view,
|
||||
|
|
@ -125,7 +184,7 @@ desktop_focus_view_or_surface(struct seat *seat, struct view *view,
|
|||
{
|
||||
assert(view || surface);
|
||||
if (view) {
|
||||
desktop_focus_view(view, raise);
|
||||
desktop_focus_view_internal(view, raise, /*allow_delay*/ true);
|
||||
#if HAVE_XWAYLAND
|
||||
} else {
|
||||
struct wlr_xwayland_surface *xsurface =
|
||||
|
|
|
|||
|
|
@ -123,11 +123,12 @@ interactive_begin(struct view *view, enum input_mode mode, enum lab_edge edges)
|
|||
cursor_shape = LAB_CURSOR_GRAB;
|
||||
break;
|
||||
case LAB_INPUT_STATE_RESIZE: {
|
||||
if (view->shaded || view->fullscreen ||
|
||||
view->maximized == VIEW_AXIS_BOTH) {
|
||||
if (view->shaded || view->fullscreen) {
|
||||
/*
|
||||
* We don't allow resizing while shaded,
|
||||
* fullscreen or maximized in both directions.
|
||||
* We don't allow resizing while shaded or fullscreen.
|
||||
* Maximized views are handled below by un-maximizing
|
||||
* the axes being resized while keeping the current
|
||||
* geometry as the starting point.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
|
@ -141,9 +142,9 @@ interactive_begin(struct view *view, enum input_mode mode, enum lab_edge edges)
|
|||
}
|
||||
|
||||
/*
|
||||
* If tiled or maximized in only one direction, reset
|
||||
* tiled state and un-maximize the relevant axes, but
|
||||
* keep the same geometry as the starting point.
|
||||
* If tiled or maximized, reset tiled state and un-maximize
|
||||
* the axes that are being resized, but keep the same
|
||||
* geometry as the starting point.
|
||||
*/
|
||||
enum view_axis maximized = view->maximized;
|
||||
if (server.resize_edges & LAB_EDGES_LEFT_RIGHT) {
|
||||
|
|
|
|||
10
src/seat.c
10
src/seat.c
|
|
@ -328,6 +328,16 @@ configure_libinput(struct wlr_input_device *wlr_input_device)
|
|||
libinput_device_config_scroll_set_method(libinput_dev, dc->scroll_method);
|
||||
}
|
||||
|
||||
libinput_device_config_scroll_set_button(libinput_dev,
|
||||
libinput_device_config_scroll_get_default_button(libinput_dev));
|
||||
if (dc->scroll_button < 0) {
|
||||
wlr_log(WLR_INFO, "scroll button not configured");
|
||||
} else {
|
||||
wlr_log(WLR_INFO, "scroll button configured (%d)",
|
||||
dc->scroll_button);
|
||||
libinput_device_config_scroll_set_button(libinput_dev, dc->scroll_button);
|
||||
}
|
||||
|
||||
libinput_device_config_send_events_set_mode(libinput_dev,
|
||||
libinput_device_config_send_events_get_default_mode(libinput_dev));
|
||||
if ((dc->send_events_mode != LIBINPUT_CONFIG_SEND_EVENTS_ENABLED
|
||||
|
|
|
|||
|
|
@ -89,6 +89,12 @@ reload_config_and_theme(void)
|
|||
/* Avoid UAF when dialog client is used during reconfigure */
|
||||
action_prompts_destroy();
|
||||
|
||||
/*
|
||||
* Cancel any pending auto-raise before reloading config in case the
|
||||
* raiseOnFocusDelay option was disabled or changed.
|
||||
*/
|
||||
desktop_cancel_pending_auto_raise();
|
||||
|
||||
scaled_buffer_invalidate_sharing();
|
||||
rcxml_finish();
|
||||
rcxml_read(rc.config_file);
|
||||
|
|
|
|||
|
|
@ -2521,6 +2521,10 @@ view_destroy(struct view *view)
|
|||
server.active_view = NULL;
|
||||
}
|
||||
|
||||
if (server.pending_auto_raise_view == view) {
|
||||
desktop_cancel_pending_auto_raise();
|
||||
}
|
||||
|
||||
if (server.session_lock_manager->last_active_view == view) {
|
||||
server.session_lock_manager->last_active_view = NULL;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue