Skip to content

Commit 51e1ff2

Browse files
authored
Merge pull request #64 from gnustep/_NET_WORKAREA
Add support for the _NET_WORKAREA property
2 parents a7094de + 423a316 commit 51e1ff2

File tree

2 files changed

+125
-27
lines changed

2 files changed

+125
-27
lines changed

ChangeLog

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
2025-12-18 Richard Frith-Macdonald <[email protected]>
23

34
* Source/x11/XGServer.m:
@@ -8,12 +9,17 @@
89
to the root window to tell it that startup is over.
910
This is an attempt to fix issue #62 on github by implementing the
1011
XDG startup notification mechanism.
11-
12+
13+
2025-12-17 Richard Frith-Macdonald <[email protected]>
14+
15+
* Source/x11/XGServerWindow.m:
16+
Implement support for _NET_WORKAREA as suggested by Fred
17+
1218
2025-05-21 Fred Kiefer <[email protected]>
1319

1420
* Source/x11/scale.c,
1521
* Source/x11/xutil.c: Update function declaration to modern C.
16-
22+
1723
2025-02-11 Richard Frith-Macdonald <[email protected]>
1824

1925
* ANNOUNCE:

Source/x11/XGServerWindow.m

Lines changed: 117 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4510,7 +4510,74 @@ - (void) freecursor: (void*) cid
45104510

45114511
return scrSize;
45124512
}
4513-
4513+
4514+
/* Gets the work areas (if the window manager supports _NET_WORKAREA) of the
4515+
* monitors/screens for the display. These are supposed to be the extents of
4516+
* the screen that we can use without trspassing on areas reservced for the
4517+
* window manager.
4518+
*/
4519+
static NSArray *
4520+
_workAreas(Display *dpy, Window root)
4521+
{
4522+
Atom workarea_atom;
4523+
Atom type;
4524+
int format;
4525+
int status;
4526+
unsigned long *items;
4527+
unsigned long nitems;
4528+
unsigned long bytes_after;
4529+
unsigned char *data = NULL;
4530+
unsigned count;
4531+
unsigned index;
4532+
NSMutableArray *array;
4533+
4534+
workarea_atom = XInternAtom(dpy, "_NET_WORKAREA", False);
4535+
status = XGetWindowProperty(dpy, root, workarea_atom,
4536+
0, /* offset */
4537+
(~0L), /* read all items */
4538+
False,
4539+
XA_CARDINAL,
4540+
&type,
4541+
&format,
4542+
&nitems,
4543+
&bytes_after,
4544+
&data
4545+
);
4546+
4547+
if (status != Success || !data)
4548+
{
4549+
NSLog(@"Failed to get _NET_WORKAREA\n");
4550+
return nil;
4551+
}
4552+
if (format != 32)
4553+
{
4554+
XFree(data);
4555+
return nil;
4556+
}
4557+
4558+
items = (unsigned long *)data;
4559+
count = nitems / 4;
4560+
array = [NSMutableArray arrayWithCapacity: count];
4561+
for (index = 0; index < count; index++)
4562+
{
4563+
NSRect frame;
4564+
4565+
frame.origin.x = (uint32_t)*items++;
4566+
frame.origin.y = (uint32_t)*items++;
4567+
frame.size.width = (uint32_t)*items++;
4568+
frame.size.height = (uint32_t)*items++;
4569+
// X coordinates need to be flipped to OpenStep coordinates
4570+
if (frame.origin.y > 0.0)
4571+
{
4572+
frame.size.height -= frame.origin.y;
4573+
frame.origin.y = 0.0;
4574+
}
4575+
[array addObject: [NSValue valueWithRect: frame]];
4576+
}
4577+
XFree(data);
4578+
return array;
4579+
}
4580+
45144581

45154582
/* This method assumes that we deal with one X11 screen - `defScreen`.
45164583
Basically it means that we have DISPLAY variable set to `:0.0`.
@@ -4524,16 +4591,18 @@ - (void) freecursor: (void*) cid
45244591
We map XRandR monitors (outputs) to NSScreen. */
45254592
- (NSArray *)screenList
45264593
{
4594+
Window root = [self xDisplayRootWindow];
4595+
NSArray *workAreas = _workAreas(dpy, root);
45274596
xScreenSize = _screenSize(dpy, defScreen);
45284597

45294598
monitorsCount = 0;
4530-
if (monitors != NULL) {
4531-
NSZoneFree([self zone], monitors);
4532-
monitors = NULL;
4533-
}
4599+
if (monitors != NULL)
4600+
{
4601+
NSZoneFree([self zone], monitors);
4602+
monitors = NULL;
4603+
}
45344604

45354605
#ifdef HAVE_XRANDR
4536-
Window root = [self xDisplayRootWindow];
45374606
XRRScreenResources *screen_res = XRRGetScreenResources(dpy, root);
45384607

45394608
if (screen_res != NULL)
@@ -4543,38 +4612,58 @@ - (NSArray *)screenList
45434612
{
45444613
int i;
45454614
int mi;
4546-
NSMutableArray *tmpScreens = [NSMutableArray arrayWithCapacity: monitorsCount];
4615+
NSMutableArray *tmpScreens;
45474616
RROutput primary_output = XRRGetOutputPrimary(dpy, root);
45484617

4549-
monitors = NSZoneMalloc([self zone], monitorsCount * sizeof(MonitorDevice));
4618+
tmpScreens = [NSMutableArray arrayWithCapacity: monitorsCount];
4619+
4620+
monitors = NSZoneMalloc([self zone],
4621+
monitorsCount * sizeof(MonitorDevice));
45504622

45514623
for (i = 0, mi = 0; i < screen_res->noutput; i++)
45524624
{
45534625
XRROutputInfo *output_info;
45544626

4555-
output_info = XRRGetOutputInfo(dpy, screen_res, screen_res->outputs[i]);
4627+
output_info = XRRGetOutputInfo(dpy,
4628+
screen_res, screen_res->outputs[i]);
45564629
if (output_info->crtc)
45574630
{
45584631
XRRCrtcInfo *crtc_info;
45594632

4560-
crtc_info = XRRGetCrtcInfo(dpy, screen_res, output_info->crtc);
4633+
crtc_info = XRRGetCrtcInfo(dpy,
4634+
screen_res, output_info->crtc);
45614635

45624636
monitors[mi].screen_id = defScreen;
45634637
monitors[mi].depth = [self windowDepthForScreen: mi];
4564-
monitors[mi].resolution = [self resolutionForScreen: defScreen];
4565-
/* Transform coordinates from Xlib (flipped) to OpenStep (unflippped).
4566-
Windows and screens should have the same coordinate system. */
4567-
monitors[mi].frame =
4568-
NSMakeRect(crtc_info->x,
4569-
xScreenSize.height - crtc_info->height - crtc_info->y,
4570-
crtc_info->width,
4571-
crtc_info->height);
4638+
monitors[mi].resolution
4639+
= [self resolutionForScreen: defScreen];
4640+
if ([workAreas count] > mi)
4641+
{
4642+
monitors[mi].frame =
4643+
[[workAreas objectAtIndex: mi] rectValue];
4644+
}
4645+
else
4646+
{
4647+
/* Transform coordinates from Xlib (flipped)
4648+
* to OpenStep (unflipped).
4649+
* Windows and screens should have the same
4650+
* coordinate system.
4651+
*/
4652+
monitors[mi].frame =
4653+
NSMakeRect(crtc_info->x,
4654+
xScreenSize.height - crtc_info->height - crtc_info->y,
4655+
crtc_info->width,
4656+
crtc_info->height);
4657+
}
45724658
/* Add monitor ID (index in monitors array).
4573-
Put primary monitor ID at index 0 since NSScreen get this as main
4574-
screen if application has no key window. */
4659+
* Put primary monitor ID at index 0 since
4660+
* NSScreen gets this as main screen if application
4661+
* has no key window.
4662+
*/
45754663
if (screen_res->outputs[i] == primary_output)
45764664
{
4577-
[tmpScreens insertObject: [NSNumber numberWithInt: mi] atIndex: 0];
4665+
[tmpScreens insertObject: [NSNumber numberWithInt: mi]
4666+
atIndex: 0];
45784667
}
45794668
else
45804669
{
@@ -4611,6 +4700,11 @@ - (NSArray *)screenList
46114700
monitors[0].depth = [self windowDepthForScreen: 0];
46124701
monitors[0].resolution = [self resolutionForScreen: defScreen];
46134702
monitors[0].frame = NSMakeRect(0, 0, xScreenSize.width, xScreenSize.height);
4703+
4704+
if ([workAreas count] > 0)
4705+
{
4706+
monitors[0].frame = [[workAreas firstObject] rectValue];
4707+
}
46144708
return [NSArray arrayWithObject: [NSNumber numberWithInt: defScreen]];
46154709
}
46164710

@@ -4861,8 +4955,7 @@ - (unsigned int) desktopNumberForScreen: (int)screen
48614955
unsigned int number = 0;
48624956

48634957
num = (unsigned int*)PropGetCheckProperty(dpy, RootWindow(dpy, screen),
4864-
generic._NET_CURRENT_DESKTOP_ATOM, XA_CARDINAL,
4865-
32, 1, &c);
4958+
generic._NET_CURRENT_DESKTOP_ATOM, XA_CARDINAL, 32, 1, &c);
48664959

48674960
if (num)
48684961
{
@@ -4897,8 +4990,7 @@ - (unsigned int) desktopNumberForWindow: (int)win
48974990
return 0;
48984991

48994992
num = (unsigned int*)PropGetCheckProperty(dpy, window->ident,
4900-
generic._NET_WM_DESKTOP_ATOM, XA_CARDINAL,
4901-
32, 1, &c);
4993+
generic._NET_WM_DESKTOP_ATOM, XA_CARDINAL, 32, 1, &c);
49024994

49034995
if (num)
49044996
{

0 commit comments

Comments
 (0)