phase 1-2: wl_screen_refresh_heads() enumerates all outputs from wlr_output_layout, populates heads/head_count/primary_head and sets correct scr_width/scr_height from bounding box
This commit is contained in:
parent
57a8973bc2
commit
c5ba4baea0
|
|
@ -0,0 +1,481 @@
|
|||
# WindowMaker Multi-Monitor Implementation Plan
|
||||
|
||||
## Purpose
|
||||
|
||||
Implement multi-monitor support in a way that another coding agent can execute with minimal guesswork.
|
||||
|
||||
This plan is written for the current `wmaker` tree and assumes:
|
||||
- X11 and Wayland backends both remain supported
|
||||
- shared policy code should continue to use the existing `head` abstraction
|
||||
- the initial goal is **correct multi-monitor geometry and behavior**, not a redesign of workspaces
|
||||
|
||||
## Scope
|
||||
|
||||
### In scope
|
||||
- Populate `WScreen.heads[]`, `head_count`, and `primary_head` correctly on both backends
|
||||
- Make Wayland support multiple outputs instead of only one
|
||||
- Recompute monitor geometry on output changes
|
||||
- Keep placement, maximize, fullscreen, icons, dock reservations, and menus head-aware
|
||||
- Handle output hotplug without leaving windows off-screen
|
||||
- Preserve existing single-monitor behavior
|
||||
|
||||
### Out of scope for phase 1
|
||||
- Per-monitor workspaces
|
||||
- Per-monitor dock/clip instances
|
||||
- Full mixed-DPI polish beyond basic correctness
|
||||
|
||||
---
|
||||
|
||||
## Existing architecture to preserve
|
||||
|
||||
### Shared abstraction
|
||||
The core already has a backend-neutral monitor/head abstraction.
|
||||
|
||||
Relevant files:
|
||||
- `src/screen.h`
|
||||
- `src/xinerama.h`
|
||||
- `src/xinerama.c`
|
||||
|
||||
Important fields in `WScreen`:
|
||||
- `heads`
|
||||
- `head_count`
|
||||
- `primary_head`
|
||||
- `usableArea`
|
||||
- `totalUsableArea`
|
||||
|
||||
Important helper APIs:
|
||||
- `wGetHeadForRect`
|
||||
- `wGetHeadForWindow`
|
||||
- `wGetHeadRelativeToCurrentHead`
|
||||
- `wGetHeadForPoint`
|
||||
- `wGetHeadForPointerLocation`
|
||||
- `wGetRectForHead`
|
||||
- `wGetUsableAreaForHead`
|
||||
- `wGetPointToCenterRectInHead`
|
||||
|
||||
### Existing backend support
|
||||
|
||||
#### X11
|
||||
- Monitor enumeration already exists in:
|
||||
- `src/backend/x11/x11_monitor.c`
|
||||
- Uses Xinerama with RandR screen-change subscriptions
|
||||
|
||||
#### Wayland
|
||||
- Output layout support already exists via wlroots:
|
||||
- `src/backend/wayland/wl_backend.c`
|
||||
- `src/backend/wayland/wl_output.c`
|
||||
- `src/backend/wayland/wl_screen.c`
|
||||
- Current limitation:
|
||||
- `wl_screen.c` populates only `heads[0]`
|
||||
- some Wayland code assumes `usableArea[0]`
|
||||
|
||||
---
|
||||
|
||||
## Non-goals and policy choices
|
||||
|
||||
### Workspace policy
|
||||
Do **not** implement per-monitor workspaces in this effort.
|
||||
|
||||
Use this policy instead:
|
||||
- a workspace still spans the full virtual desktop
|
||||
- placement/maximize/focus/icon logic remains **head-aware within that workspace**
|
||||
|
||||
This keeps the patch set tractable and aligns with the current helper model.
|
||||
|
||||
### Dock / Clip policy
|
||||
For now:
|
||||
- keep one logical Dock and one logical Clip model
|
||||
- make their geometry reservations and placement logic head-aware
|
||||
|
||||
Do not introduce per-head docks in this plan.
|
||||
|
||||
---
|
||||
|
||||
## Canonical monitor contract
|
||||
|
||||
Before changing behavior, normalize the meaning of `heads[]`.
|
||||
|
||||
### Required invariants
|
||||
1. `scr->heads` contains monitor rectangles in **global root coordinates**.
|
||||
2. `scr->head_count >= 1` after screen initialization succeeds.
|
||||
3. `scr->primary_head` is always a valid index when `head_count > 0`.
|
||||
4. `scr->scr_width` / `scr->scr_height` represent the bounding box of the full virtual desktop.
|
||||
5. `wGetRectForHead(scr, i)` must always return a valid monitor rectangle for `0 <= i < head_count`.
|
||||
6. Single-monitor mode should still behave correctly.
|
||||
|
||||
### Preferred normalization
|
||||
Use **one explicit head even in single-monitor mode**.
|
||||
|
||||
That means avoiding the old pattern where `head_count == 0` implies fallback-to-single-head behavior.
|
||||
|
||||
If changing all callers at once is too risky, do this in two steps:
|
||||
1. preserve compatibility in helpers
|
||||
2. gradually move callers to assume `head_count >= 1`
|
||||
|
||||
---
|
||||
|
||||
## Execution plan
|
||||
|
||||
## Phase 1 — Audit and normalize head initialization
|
||||
|
||||
### Goal
|
||||
Make head data reliable and backend-neutral before extending Wayland.
|
||||
|
||||
### Files
|
||||
- `src/screen.h`
|
||||
- `src/xinerama.h`
|
||||
- `src/xinerama.c`
|
||||
- `src/screen.c`
|
||||
- `src/backend/x11/x11_monitor.c`
|
||||
|
||||
### Tasks
|
||||
1. Audit all places that read:
|
||||
- `scr->heads`
|
||||
- `scr->head_count`
|
||||
- `scr->primary_head`
|
||||
2. Decide whether to enforce `head_count >= 1` immediately or via compatibility layer.
|
||||
3. Ensure the X11 path populates a valid single fallback head when Xinerama is inactive.
|
||||
4. Ensure head arrays are allocated/freed consistently.
|
||||
5. Add comments documenting the head contract.
|
||||
|
||||
### Acceptance criteria
|
||||
- X11 single-monitor behavior is unchanged.
|
||||
- There is a clear contract for `head_count`, `heads`, and `primary_head`.
|
||||
- Helper functions behave correctly with one or many heads.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2 — Implement Wayland monitor enumeration
|
||||
|
||||
### Goal
|
||||
Populate all heads from `wlr_output_layout`, not just one.
|
||||
|
||||
### Files
|
||||
- `src/backend/wayland/wl_screen.c`
|
||||
- `src/backend/wayland/wl_output.c`
|
||||
- `src/backend/wayland/wl_backend.c`
|
||||
- `src/backend/backend_types.h`
|
||||
|
||||
### Tasks
|
||||
1. Audit the Wayland global state for available outputs and layout access.
|
||||
2. In `wl_screen_open()` or the appropriate geometry refresh path:
|
||||
- enumerate all active outputs
|
||||
- query each output's box via `wlr_output_layout_get_box`
|
||||
- build a `WHeadGeometry[]`
|
||||
3. Set:
|
||||
- `scr->heads`
|
||||
- `scr->head_count`
|
||||
- `scr->primary_head`
|
||||
4. Set `scr->scr_width` and `scr->scr_height` from the **union of all head rectangles**, not from a single output.
|
||||
5. Preserve deterministic ordering of heads.
|
||||
- Recommended: sort by `(x, y)` or preserve wlroots layout iteration order if stable.
|
||||
6. Choose primary head policy.
|
||||
- Recommended initial policy: first active output or currently selected backend primary output.
|
||||
|
||||
### Acceptance criteria
|
||||
- On Wayland with two outputs, `scr->head_count == 2`.
|
||||
- `wGetRectForHead()` returns both outputs with correct geometry.
|
||||
- `scr->scr_width` / `scr->scr_height` reflect the virtual desktop bounds.
|
||||
|
||||
### Notes for the implementing agent
|
||||
- Keep this backend-only.
|
||||
- Do not add special placement logic here.
|
||||
- Just make monitor geometry correct and complete.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3 — Add dynamic output refresh / hotplug support
|
||||
|
||||
### Goal
|
||||
Rebuild monitor geometry whenever outputs change.
|
||||
|
||||
### Files
|
||||
- `src/backend/wayland/wl_output.c`
|
||||
- `src/backend/wayland/wl_screen.c`
|
||||
- `src/screen.c`
|
||||
- optionally `src/window.c`, `src/dock.c`
|
||||
|
||||
### Tasks
|
||||
1. Identify Wayland output lifecycle hooks:
|
||||
- new output
|
||||
- destroyed/removed output
|
||||
- layout or mode change
|
||||
2. Add a shared helper to rebuild screen head data.
|
||||
- Example helper name: `wl_screen_refresh_heads(scr)`
|
||||
3. Recompute after each relevant event:
|
||||
- heads
|
||||
- virtual bounds
|
||||
- usable areas
|
||||
4. If an output disappears, repair windows/icons that now lie outside all heads.
|
||||
|
||||
### Suggested repair policy
|
||||
For each affected window:
|
||||
1. find nearest surviving head
|
||||
2. preserve relative position when possible
|
||||
3. clamp inside that head if necessary
|
||||
4. fall back to centering in `primary_head`
|
||||
|
||||
For icons/appicons:
|
||||
- do the same, but prefer the head they touched before removal
|
||||
|
||||
### Acceptance criteria
|
||||
- Plugging/unplugging outputs does not leave windows permanently off-screen.
|
||||
- Head helpers reflect the new output topology immediately.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4 — Make usable-area and reservations per-head
|
||||
|
||||
### Goal
|
||||
Ensure placement/maximize respects per-head reserved areas.
|
||||
|
||||
### Files
|
||||
- `src/xinerama.c`
|
||||
- `src/screen.c`
|
||||
- `src/dock.c`
|
||||
- `src/backend/wayland/wl_dock.c`
|
||||
|
||||
### Known problem to fix
|
||||
Wayland dock code currently assumes `scr->usableArea[0]` in places.
|
||||
|
||||
### Tasks
|
||||
1. Audit all reads/writes of:
|
||||
- `scr->usableArea`
|
||||
- `scr->totalUsableArea`
|
||||
- `scr->reservedAreas`
|
||||
2. Ensure these arrays are sized for all heads.
|
||||
3. Ensure dock/clip reservations affect the correct head.
|
||||
4. When monitor geometry changes, recompute all per-head usable areas.
|
||||
5. Remove hardcoded `[0]` assumptions.
|
||||
|
||||
### Acceptance criteria
|
||||
- Docks and clips reserve space only on the relevant head.
|
||||
- Maximize avoids reserved space on the current head.
|
||||
- Single-monitor behavior remains unchanged.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5 — Audit all head-aware placement and movement paths
|
||||
|
||||
### Goal
|
||||
Make all geometry-sensitive actions consistent across monitors.
|
||||
|
||||
### Files to audit
|
||||
- `src/placement.c`
|
||||
- `src/window.c`
|
||||
- `src/actions.c`
|
||||
- `src/cycling.c`
|
||||
- `src/rootmenu.c`
|
||||
- `src/dialog.c`
|
||||
- `src/dock.c`
|
||||
|
||||
### Tasks
|
||||
Audit and fix the following behaviors:
|
||||
|
||||
#### New window placement
|
||||
- New windows should open on:
|
||||
- the pointer head, or
|
||||
- the owner/transient head, or
|
||||
- the current head policy already used by helpers
|
||||
|
||||
#### Restore/session placement
|
||||
- Restored geometry should be clamped or translated to a valid head.
|
||||
|
||||
#### Maximize/fullscreen
|
||||
- Maximize should apply to the window's current head unless multi-head fullscreen is explicitly requested.
|
||||
- Existing fullscreen-monitor helpers in `actions.c` should keep working.
|
||||
|
||||
#### Menus/dialogs/transients
|
||||
- Menus should open on the head that contains the invocation point.
|
||||
- Transients should prefer the owner head.
|
||||
- Dialog centering should use the correct head.
|
||||
|
||||
#### Icons / miniwindows
|
||||
- Icon placement should remain on the window's head.
|
||||
- Auto-arrange should consider all heads, not just head 0.
|
||||
|
||||
### Acceptance criteria
|
||||
- Placement/maximize/fullscreen/menus/transients/icons all behave correctly on two monitors.
|
||||
|
||||
---
|
||||
|
||||
## Phase 6 — Add explicit monitor navigation commands
|
||||
|
||||
### Goal
|
||||
Expose useful multi-monitor actions to users.
|
||||
|
||||
### Files
|
||||
- `src/actions.c`
|
||||
- `src/defaults.c`
|
||||
- `WPrefs.app/KeyboardShortcuts.c`
|
||||
- possibly menu/defaults docs
|
||||
|
||||
### Tasks
|
||||
1. Audit existing actions using:
|
||||
- `wGetHeadRelativeToCurrentHead`
|
||||
- `wGetHeadForWindow`
|
||||
2. Finish or add commands such as:
|
||||
- move window to next monitor
|
||||
- move window to previous monitor
|
||||
- move focus to next monitor
|
||||
- maximize on current monitor
|
||||
3. Expose them through defaults and WPrefs if not already exposed.
|
||||
|
||||
### Acceptance criteria
|
||||
- A user can move windows between monitors with shortcuts.
|
||||
- The actions behave correctly on X11 and Wayland.
|
||||
|
||||
---
|
||||
|
||||
## Phase 7 — Mixed scale / DPI follow-up (optional but recommended)
|
||||
|
||||
### Goal
|
||||
Avoid rendering problems on mixed-scale Wayland outputs.
|
||||
|
||||
### Files
|
||||
- `src/backend/wayland/wl_output.c`
|
||||
- `src/backend/wayland/wl_screen.c`
|
||||
- WINGs font/render paths
|
||||
|
||||
### Tasks
|
||||
1. Track output scale per output/head.
|
||||
2. Set output scale in wlroots where appropriate.
|
||||
3. Feed DPI/scale into font/layout code.
|
||||
4. Validate titlebars, menus, icons, screenshots, and WINGs rendering.
|
||||
|
||||
### Acceptance criteria
|
||||
- Multi-output works correctly even when outputs have different scales.
|
||||
|
||||
---
|
||||
|
||||
## Concrete code audit checklist
|
||||
|
||||
Use this as a literal checklist while implementing.
|
||||
|
||||
### Shared monitor/head code
|
||||
- [ ] `src/xinerama.c`
|
||||
- [ ] `src/xinerama.h`
|
||||
- [ ] `src/screen.c`
|
||||
- [ ] `src/screen.h`
|
||||
|
||||
### X11 backend
|
||||
- [ ] `src/backend/x11/x11_monitor.c`
|
||||
|
||||
### Wayland backend
|
||||
- [ ] `src/backend/wayland/wl_backend.c`
|
||||
- [ ] `src/backend/wayland/wl_output.c`
|
||||
- [ ] `src/backend/wayland/wl_screen.c`
|
||||
- [ ] `src/backend/wayland/wl_dock.c`
|
||||
|
||||
### Placement/window policy
|
||||
- [ ] `src/placement.c`
|
||||
- [ ] `src/window.c`
|
||||
- [ ] `src/actions.c`
|
||||
- [ ] `src/cycling.c`
|
||||
- [ ] `src/rootmenu.c`
|
||||
- [ ] `src/dialog.c`
|
||||
- [ ] `src/dock.c`
|
||||
|
||||
### User-facing configuration
|
||||
- [ ] `src/defaults.c`
|
||||
- [ ] `WPrefs.app/KeyboardShortcuts.c`
|
||||
- [ ] docs / release notes
|
||||
|
||||
---
|
||||
|
||||
## Suggested implementation order for an agent
|
||||
|
||||
If working incrementally, use this order:
|
||||
|
||||
1. **Normalize head contract**
|
||||
2. **Enumerate all Wayland outputs into `heads[]`**
|
||||
3. **Set virtual desktop bounds correctly**
|
||||
4. **Recompute heads on hotplug / output change**
|
||||
5. **Fix per-head usable area and dock reservations**
|
||||
6. **Audit maximize/placement/fullscreen**
|
||||
7. **Audit menus/transients/icons**
|
||||
8. **Add monitor-navigation actions**
|
||||
9. **Do scale/DPI follow-up**
|
||||
|
||||
Do not start with user-facing shortcuts or DPI.
|
||||
Start with geometry correctness.
|
||||
|
||||
---
|
||||
|
||||
## Test matrix
|
||||
|
||||
## X11 tests
|
||||
- [ ] single monitor
|
||||
- [ ] dual monitor horizontal
|
||||
- [ ] dual monitor vertical
|
||||
- [ ] mixed resolutions
|
||||
- [ ] RandR hotplug/unplug
|
||||
- [ ] maximize on each head
|
||||
- [ ] fullscreen on each head
|
||||
- [ ] menu placement
|
||||
- [ ] dialog placement
|
||||
- [ ] icon placement
|
||||
|
||||
## Wayland tests
|
||||
Use nested mode if needed.
|
||||
|
||||
Suggested setup:
|
||||
- `WMAKER_WAYLAND_NESTED=1`
|
||||
- adjust outputs with `wlr-randr`
|
||||
|
||||
Run:
|
||||
- [ ] single output
|
||||
- [ ] two outputs horizontal
|
||||
- [ ] two outputs vertical
|
||||
- [ ] asymmetric offset layout
|
||||
- [ ] output removal with windows present
|
||||
- [ ] output addition after startup
|
||||
- [ ] maximize/fullscreen correctness
|
||||
- [ ] dock/clip reservation correctness
|
||||
- [ ] pointer-head placement correctness
|
||||
- [ ] WINGs app placement correctness
|
||||
- [ ] XWayland client placement correctness
|
||||
|
||||
---
|
||||
|
||||
## Debugging guidance for the implementing agent
|
||||
|
||||
When behavior is wrong, log these values first:
|
||||
- `scr->head_count`
|
||||
- all `scr->heads[i]`
|
||||
- `scr->primary_head`
|
||||
- `scr->scr_width`, `scr->scr_height`
|
||||
- result of `wGetHeadForWindow()` for the affected window
|
||||
- result of `wGetHeadForPointerLocation()` during placement
|
||||
- per-head `usableArea` and `totalUsableArea`
|
||||
|
||||
For Wayland output changes, log:
|
||||
- output add/remove
|
||||
- output layout box for each output
|
||||
- geometry refresh entry/exit
|
||||
- window migration decisions on output removal
|
||||
|
||||
---
|
||||
|
||||
## Definition of done
|
||||
|
||||
This effort is complete when all of the following are true:
|
||||
- `heads[]` is correct on X11 and Wayland
|
||||
- Wayland supports more than one output
|
||||
- output hotplug updates geometry correctly
|
||||
- windows never remain stranded off-screen after output removal
|
||||
- maximize/fullscreen/placement/icons/menus are head-aware
|
||||
- dock/clip reservations are per-head
|
||||
- single-monitor behavior is unchanged
|
||||
|
||||
---
|
||||
|
||||
## Minimal deliverable if time is limited
|
||||
|
||||
If this must be split across multiple PRs, the **minimum useful first PR** is:
|
||||
1. normalize monitor contract
|
||||
2. populate all Wayland heads
|
||||
3. set correct virtual desktop bounds
|
||||
4. fix obvious `usableArea[0]` assumptions
|
||||
|
||||
That alone provides the base needed for all follow-up work.
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
|
|
@ -26,17 +28,87 @@ extern void fb_attach_scene_buf_listener(struct wl_frame_buf *fb);
|
|||
|
||||
void *W_RegisterBacking(unsigned long id, void *img);
|
||||
|
||||
#define MAX_WL_HEADS 16
|
||||
|
||||
/* Rebuild scr->heads from the wlr_output_layout. Called during screen
|
||||
* init and on output hotplug. */
|
||||
static void
|
||||
wl_screen_refresh_heads(WScreen *scr)
|
||||
{
|
||||
/* Free old head array if any */
|
||||
if (scr->heads) {
|
||||
wfree(scr->heads);
|
||||
scr->heads = NULL;
|
||||
}
|
||||
scr->head_count = 0;
|
||||
scr->primary_head = 0;
|
||||
|
||||
if (!wl_state.output_layout)
|
||||
return;
|
||||
|
||||
/* Count outputs first */
|
||||
int count = 0;
|
||||
struct wlr_output_layout_output *lo;
|
||||
wl_list_for_each(lo, &wl_state.output_layout->outputs, link) {
|
||||
count++;
|
||||
}
|
||||
if (count == 0)
|
||||
return;
|
||||
if (count > MAX_WL_HEADS)
|
||||
count = MAX_WL_HEADS;
|
||||
|
||||
scr->heads = wmalloc(sizeof(WHeadGeometry) * count);
|
||||
scr->head_count = count;
|
||||
|
||||
/* Compute bounding box across all heads */
|
||||
int min_x = INT_MAX, min_y = INT_MAX;
|
||||
int max_x = 0, max_y = 0;
|
||||
int idx = 0;
|
||||
wl_list_for_each(lo, &wl_state.output_layout->outputs, link) {
|
||||
if (idx >= count) break;
|
||||
struct wlr_box box = {0};
|
||||
wlr_output_layout_get_box(wl_state.output_layout,
|
||||
lo->output, &box);
|
||||
if (box.width == 0 || box.height == 0) {
|
||||
box.x = 0; box.y = 0;
|
||||
box.width = (int)lo->output->width;
|
||||
box.height = (int)lo->output->height;
|
||||
}
|
||||
scr->heads[idx].x = box.x;
|
||||
scr->heads[idx].y = box.y;
|
||||
scr->heads[idx].width = box.width;
|
||||
scr->heads[idx].height = box.height;
|
||||
if (box.x < min_x) min_x = box.x;
|
||||
if (box.y < min_y) min_y = box.y;
|
||||
if (box.x + box.width > max_x) max_x = box.x + box.width;
|
||||
if (box.y + box.height > max_y) max_y = box.y + box.height;
|
||||
idx++;
|
||||
}
|
||||
|
||||
scr->scr_width = max_x - min_x;
|
||||
scr->scr_height = max_y - min_y;
|
||||
|
||||
/* Use the first output's geometry for scr_width/scr_height if we
|
||||
* only got a single output anyway (the bounding box is the same). */
|
||||
if (count == 1) {
|
||||
scr->scr_width = scr->heads[0].width;
|
||||
scr->scr_height = scr->heads[0].height;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Screen open/close */
|
||||
|
||||
void
|
||||
wl_screen_open(WScreen *scr)
|
||||
{
|
||||
/* Set geometry from the headless output created in display_open(). */
|
||||
scr->scr_width = wl_state.output ?
|
||||
(int)wl_state.output->width : 1920;
|
||||
scr->scr_height = wl_state.output ?
|
||||
(int)wl_state.output->height : 1080;
|
||||
wl_screen_refresh_heads(scr);
|
||||
|
||||
/* Fallback if no output is available yet */
|
||||
if (scr->head_count == 0) {
|
||||
scr->scr_width = 1920;
|
||||
scr->scr_height = 1080;
|
||||
}
|
||||
scr->depth = 24;
|
||||
scr->root_win = (WNativeWindow)0x0FFFFFFF; /* synthetic root window ID */
|
||||
scr->colormap = 0;
|
||||
|
|
@ -518,37 +590,26 @@ wl_screen_load_tech_font(WScreen *scr)
|
|||
void
|
||||
wl_monitors_query(WScreen *scr, WHeadGeometry **heads_out, int *count_out)
|
||||
{
|
||||
(void)scr;
|
||||
|
||||
if (!wl_state.output) {
|
||||
if (!wl_state.output_layout) {
|
||||
*heads_out = NULL;
|
||||
*count_out = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
WHeadGeometry *heads = wmalloc(sizeof(WHeadGeometry));
|
||||
/* Rebuild head data from current layout */
|
||||
wl_screen_refresh_heads(scr);
|
||||
|
||||
if (wl_state.output_layout) {
|
||||
struct wlr_box box = {0};
|
||||
wlr_output_layout_get_box(wl_state.output_layout, wl_state.output, &box);
|
||||
if (box.width > 0 || box.height > 0) {
|
||||
heads[0].x = box.x;
|
||||
heads[0].y = box.y;
|
||||
heads[0].width = box.width;
|
||||
heads[0].height = box.height;
|
||||
} else {
|
||||
heads[0].x = heads[0].y = 0;
|
||||
heads[0].width = (int)wl_state.output->width;
|
||||
heads[0].height = (int)wl_state.output->height;
|
||||
}
|
||||
} else {
|
||||
heads[0].x = heads[0].y = 0;
|
||||
heads[0].width = (int)wl_state.output->width;
|
||||
heads[0].height = (int)wl_state.output->height;
|
||||
if (scr->head_count == 0 || !scr->heads) {
|
||||
*heads_out = NULL;
|
||||
*count_out = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
*heads_out = heads;
|
||||
*count_out = 1;
|
||||
/* Return a copy the caller owns */
|
||||
WHeadGeometry *out = wmalloc(sizeof(WHeadGeometry) * scr->head_count);
|
||||
memcpy(out, scr->heads, sizeof(WHeadGeometry) * scr->head_count);
|
||||
*heads_out = out;
|
||||
*count_out = scr->head_count;
|
||||
}
|
||||
|
||||
void wl_monitors_select_events(WScreen *scr) { (void)scr; }
|
||||
|
|
|
|||
Loading…
Reference in New Issue