forked from 12to11/12to11

* 12to11.c (XLMain): Initialize timestamp tracking. * 12to11.man: Document *.useDirectPresentation resource. * atoms.c (names): Add _NET_WM_PID and _NET_WM_PING. (XLInitAtoms): Likewise. * compositor.h (struct _RenderFuncs): Update doc of cancel_presentation. (enum _FrameMode): Add ModeNotifyDisablePresent. (struct _XdgRoleList, struct _XdgWmBase): New structs. * frame_clock.c (StartFrame): Return if the clock was really started. (XLFrameClockStartFrame): Likewise. (XLInitFrameClock): Move Sync extension initialization to InitTime. * picture_renderer.c (struct _PresentCompletionCallback) (struct _PictureTarget, InitSynchronizedPresentation) (InitRenderFuncs, TargetFromDrawable, DestroyRenderTarget) (PresentToWindow, CancelPresentationCallback, AddRenderFlag) (HandlePresentCompleteNotify): Link structure on target. When synchronized presentation is enabled, use the approriate msc to present, and record the last known msc. * run.c (HandleOneXEvent): Handle timestamp events. * subcompositor.c (SubcompositorUpdate): Note frame with ModeNotifyDisablePresent. (FindSystemCounter, ValueToScalar, ScalarToValue, StartAlarms) (HandleAlarmNotify, HandleOneXEventForTime, InitTime): New functions. * xdg_surface.c (struct _XdgRole): New fields `link' and `wm_base'. (struct _PingEvent): New structure. (ReleaseBacking): Release all ping events. (NoteFrame, WriteRedirectProperty): Allow unredirection under some circumstances. (XLGetXdgSurface): Attach wm base. (XLXdgRoleHandlePing, ReplyPingEvent, XLXdgRoleReplyPing): New function. * xdg_toplevel.c (GetClientMachine): New function. (WriteCredentialProperties): New function. (Attach): Write credential properties. (ReplyToPing): New function. (XLHandleXEventForXdgToplevels): Handle ping events. * xdg_wm.c (Pong): Reply to ping events once pong is received from the client. (HandleResourceDestroy): Detach all surfaces and run their ping events. (HandleBind): Allocate memory for XdgWmBase. (XLXdgWmBaseSendPing): New function.
301 lines
8.5 KiB
C
301 lines
8.5 KiB
C
/* Wayland compositor running on top of an X server.
|
|
|
|
Copyright (C) 2022 to various contributors.
|
|
|
|
This file is part of 12to11.
|
|
|
|
12to11 is free software: you can redistribute it and/or modify it
|
|
under the terms of the GNU General Public License as published by the
|
|
Free Software Foundation, either version 3 of the License, or (at your
|
|
option) any later version.
|
|
|
|
12to11 is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with 12to11. If not, see <https://www.gnu.org/licenses/>. */
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "compositor.h"
|
|
|
|
#define AtomTableSize 256
|
|
|
|
typedef struct _AtomTable AtomTable;
|
|
|
|
/* This is automatically generated by mime4.awk. */
|
|
Atom DirectTransferAtoms;
|
|
|
|
/* Simple hash table for atoms. */
|
|
|
|
struct _AtomTable
|
|
{
|
|
/* Atom array indexed by table size. */
|
|
Atom *atoms[AtomTableSize];
|
|
|
|
/* Atom name array indexed by table size. */
|
|
char **names[AtomTableSize];
|
|
|
|
/* Size of each array. */
|
|
ptrdiff_t atoms_length[AtomTableSize];
|
|
};
|
|
|
|
/* Array of all atom names. */
|
|
static const char *names[] =
|
|
{
|
|
"_NET_WM_OPAQUE_REGION",
|
|
"_XL_BUFFER_RELEASE",
|
|
"_NET_WM_SYNC_REQUEST_COUNTER",
|
|
"_NET_WM_FRAME_DRAWN",
|
|
"WM_DELETE_WINDOW",
|
|
"WM_PROTOCOLS",
|
|
"_NET_SUPPORTING_WM_CHECK",
|
|
"_NET_SUPPORTED",
|
|
"_NET_WM_SYNC_REQUEST",
|
|
"_MOTIF_WM_HINTS",
|
|
"_NET_WM_STATE_MAXIMIZED_VERT",
|
|
"_NET_WM_STATE_MAXIMIZED_HORZ",
|
|
"_NET_WM_STATE_FOCUSED",
|
|
"_NET_WM_STATE_FULLSCREEN",
|
|
"_NET_WM_STATE",
|
|
"_NET_WM_MOVERESIZE",
|
|
"_GTK_FRAME_EXTENTS",
|
|
"WM_TRANSIENT_FOR",
|
|
"_XL_DMA_BUF_CREATED",
|
|
"_GTK_SHOW_WINDOW_MENU",
|
|
"_NET_WM_ALLOWED_ACTIONS",
|
|
"_NET_WM_ACTION_FULLSCREEN",
|
|
"_NET_WM_ACTION_MAXIMIZE_HORZ",
|
|
"_NET_WM_ACTION_MAXIMIZE_VERT",
|
|
"_NET_WM_ACTION_MINIMIZE",
|
|
"INCR",
|
|
"CLIPBOARD",
|
|
"TARGETS",
|
|
"UTF8_STRING",
|
|
"_XL_SERVER_TIME_ATOM",
|
|
"MULTIPLE",
|
|
"TIMESTAMP",
|
|
"ATOM_PAIR",
|
|
"_NET_WM_NAME",
|
|
"WM_NAME",
|
|
"MANAGER",
|
|
"_XSETTINGS_SETTINGS",
|
|
"libinput Scroll Methods Available",
|
|
"XdndAware",
|
|
"XdndSelection",
|
|
"XdndTypeList",
|
|
"XdndActionCopy",
|
|
"XdndActionMove",
|
|
"XdndActionLink",
|
|
"XdndActionAsk",
|
|
"XdndActionPrivate",
|
|
"XdndActionList",
|
|
"XdndActionDescription",
|
|
"XdndProxy",
|
|
"XdndEnter",
|
|
"XdndPosition",
|
|
"XdndStatus",
|
|
"XdndLeave",
|
|
"XdndDrop",
|
|
"XdndFinished",
|
|
"_NET_WM_FRAME_TIMINGS",
|
|
"_NET_WM_BYPASS_COMPOSITOR",
|
|
"WM_STATE",
|
|
"_NET_WM_WINDOW_TYPE",
|
|
"_NET_WM_WINDOW_TYPE_MENU",
|
|
"_NET_WM_WINDOW_TYPE_DND",
|
|
"CONNECTOR_ID",
|
|
"_NET_WM_PID",
|
|
"_NET_WM_PING",
|
|
|
|
/* These are automatically generated from mime.txt. */
|
|
DirectTransferAtomNames
|
|
};
|
|
|
|
Atom _NET_WM_OPAQUE_REGION, _XL_BUFFER_RELEASE, _NET_WM_SYNC_REQUEST_COUNTER,
|
|
_NET_WM_FRAME_DRAWN, WM_DELETE_WINDOW, WM_PROTOCOLS,
|
|
_NET_SUPPORTING_WM_CHECK, _NET_SUPPORTED, _NET_WM_SYNC_REQUEST,
|
|
_MOTIF_WM_HINTS, _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ,
|
|
_NET_WM_STATE_FOCUSED, _NET_WM_STATE_FULLSCREEN, _NET_WM_STATE,
|
|
_NET_WM_MOVERESIZE, _GTK_FRAME_EXTENTS, WM_TRANSIENT_FOR,
|
|
_XL_DMA_BUF_CREATED, _GTK_SHOW_WINDOW_MENU, _NET_WM_ALLOWED_ACTIONS,
|
|
_NET_WM_ACTION_FULLSCREEN, _NET_WM_ACTION_MAXIMIZE_HORZ,
|
|
_NET_WM_ACTION_MAXIMIZE_VERT, _NET_WM_ACTION_MINIMIZE, INCR, CLIPBOARD,
|
|
TARGETS, UTF8_STRING, _XL_SERVER_TIME_ATOM, MULTIPLE, TIMESTAMP, ATOM_PAIR,
|
|
_NET_WM_NAME, WM_NAME, MANAGER, _XSETTINGS_SETTINGS,
|
|
libinput_Scroll_Methods_Available, XdndAware, XdndSelection, XdndTypeList,
|
|
XdndActionCopy, XdndActionMove, XdndActionLink, XdndActionAsk,
|
|
XdndActionPrivate, XdndActionList, XdndActionDescription, XdndProxy,
|
|
XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop, XdndFinished,
|
|
_NET_WM_FRAME_TIMINGS, _NET_WM_BYPASS_COMPOSITOR, WM_STATE,
|
|
_NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_MENU, _NET_WM_WINDOW_TYPE_DND,
|
|
CONNECTOR_ID, _NET_WM_PID, _NET_WM_PING;
|
|
|
|
XrmQuark resource_quark, app_quark, QString;
|
|
|
|
/* Hash table containing atoms. */
|
|
|
|
static AtomTable atom_table;
|
|
|
|
static unsigned int
|
|
HashAtomString (const char *string)
|
|
{
|
|
unsigned int i;
|
|
|
|
i = 3323198485ul;
|
|
for (; *string; ++string)
|
|
{
|
|
i ^= *string;
|
|
i *= 0x5bd1e995;
|
|
i ^= i >> 15;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
Atom
|
|
InternAtom (const char *name)
|
|
{
|
|
Atom atom;
|
|
unsigned int hash;
|
|
ptrdiff_t bucket_length, i;
|
|
|
|
hash = HashAtomString (name) % AtomTableSize;
|
|
bucket_length = atom_table.atoms_length[hash];
|
|
|
|
for (i = 0; i < bucket_length; ++i)
|
|
{
|
|
if (!strcmp (atom_table.names[hash][i], name))
|
|
return atom_table.atoms[hash][i];
|
|
}
|
|
|
|
atom = XInternAtom (compositor.display, name, False);
|
|
|
|
atom_table.atoms_length[hash] = ++bucket_length;
|
|
atom_table.names[hash]
|
|
= XLRealloc (atom_table.names[hash],
|
|
bucket_length * sizeof *atom_table.names);
|
|
atom_table.atoms[hash]
|
|
= XLRealloc (atom_table.atoms[hash],
|
|
bucket_length * sizeof *atom_table.atoms);
|
|
atom_table.names[hash][bucket_length - 1] = XLStrdup (name);
|
|
atom_table.atoms[hash][bucket_length - 1] = atom;
|
|
return atom;
|
|
}
|
|
|
|
void
|
|
ProvideAtom (const char *name, Atom atom)
|
|
{
|
|
unsigned int hash;
|
|
ptrdiff_t bucket_length, i;
|
|
|
|
hash = HashAtomString (name) % AtomTableSize;
|
|
bucket_length = atom_table.atoms_length[hash];
|
|
|
|
for (i = 0; i < bucket_length; ++i)
|
|
{
|
|
if (!strcmp (atom_table.names[hash][i], name))
|
|
/* The atom already exists; there is no need to update it. */
|
|
return;
|
|
}
|
|
|
|
atom_table.atoms_length[hash] = ++bucket_length;
|
|
atom_table.names[hash]
|
|
= XLRealloc (atom_table.names[hash],
|
|
bucket_length * sizeof *atom_table.names);
|
|
atom_table.atoms[hash]
|
|
= XLRealloc (atom_table.atoms[hash],
|
|
bucket_length * sizeof *atom_table.atoms);
|
|
atom_table.names[hash][bucket_length - 1] = XLStrdup (name);
|
|
atom_table.atoms[hash][bucket_length - 1] = atom;
|
|
}
|
|
|
|
void
|
|
XLInitAtoms (void)
|
|
{
|
|
Atom atoms[ArrayElements (names)];
|
|
|
|
if (!XInternAtoms (compositor.display, (char **) names,
|
|
ArrayElements (names), False,
|
|
atoms))
|
|
{
|
|
fprintf (stderr, "Failed to intern X atoms\n");
|
|
exit (1);
|
|
}
|
|
|
|
_NET_WM_OPAQUE_REGION = atoms[0];
|
|
_XL_BUFFER_RELEASE = atoms[1];
|
|
_NET_WM_SYNC_REQUEST_COUNTER = atoms[2];
|
|
_NET_WM_FRAME_DRAWN = atoms[3];
|
|
WM_DELETE_WINDOW = atoms[4];
|
|
WM_PROTOCOLS = atoms[5];
|
|
_NET_SUPPORTING_WM_CHECK = atoms[6];
|
|
_NET_SUPPORTED = atoms[7];
|
|
_NET_WM_SYNC_REQUEST = atoms[8];
|
|
_MOTIF_WM_HINTS = atoms[9];
|
|
_NET_WM_STATE_MAXIMIZED_VERT = atoms[10];
|
|
_NET_WM_STATE_MAXIMIZED_HORZ = atoms[11];
|
|
_NET_WM_STATE_FOCUSED = atoms[12];
|
|
_NET_WM_STATE_FULLSCREEN = atoms[13];
|
|
_NET_WM_STATE = atoms[14];
|
|
_NET_WM_MOVERESIZE = atoms[15];
|
|
_GTK_FRAME_EXTENTS = atoms[16];
|
|
WM_TRANSIENT_FOR = atoms[17];
|
|
_XL_DMA_BUF_CREATED = atoms[18];
|
|
_GTK_SHOW_WINDOW_MENU = atoms[19];
|
|
_NET_WM_ALLOWED_ACTIONS = atoms[20];
|
|
_NET_WM_ACTION_FULLSCREEN = atoms[21];
|
|
_NET_WM_ACTION_MAXIMIZE_HORZ = atoms[22];
|
|
_NET_WM_ACTION_MAXIMIZE_VERT = atoms[23];
|
|
_NET_WM_ACTION_MINIMIZE = atoms[24];
|
|
INCR = atoms[25];
|
|
CLIPBOARD = atoms[26];
|
|
TARGETS = atoms[27];
|
|
UTF8_STRING = atoms[28];
|
|
_XL_SERVER_TIME_ATOM = atoms[29];
|
|
MULTIPLE = atoms[30];
|
|
TIMESTAMP = atoms[31];
|
|
ATOM_PAIR = atoms[32];
|
|
_NET_WM_NAME = atoms[33];
|
|
WM_NAME = atoms[34];
|
|
MANAGER = atoms[35];
|
|
_XSETTINGS_SETTINGS = atoms[36];
|
|
libinput_Scroll_Methods_Available = atoms[37];
|
|
XdndAware = atoms[38];
|
|
XdndSelection = atoms[39];
|
|
XdndTypeList = atoms[40];
|
|
XdndActionCopy = atoms[41];
|
|
XdndActionMove = atoms[42];
|
|
XdndActionLink = atoms[43];
|
|
XdndActionAsk = atoms[44];
|
|
XdndActionPrivate = atoms[45];
|
|
XdndActionList = atoms[46];
|
|
XdndActionDescription = atoms[47];
|
|
XdndProxy = atoms[48];
|
|
XdndEnter = atoms[49];
|
|
XdndPosition = atoms[50];
|
|
XdndStatus = atoms[51];
|
|
XdndLeave = atoms[52];
|
|
XdndDrop = atoms[53];
|
|
XdndFinished = atoms[54];
|
|
_NET_WM_FRAME_TIMINGS = atoms[55];
|
|
_NET_WM_BYPASS_COMPOSITOR = atoms[56];
|
|
WM_STATE = atoms[57];
|
|
_NET_WM_WINDOW_TYPE = atoms[58];
|
|
_NET_WM_WINDOW_TYPE_MENU = atoms[59];
|
|
_NET_WM_WINDOW_TYPE_DND = atoms[60];
|
|
CONNECTOR_ID = atoms[61];
|
|
_NET_WM_PID = atoms[62];
|
|
_NET_WM_PING = atoms[63];
|
|
|
|
/* This is automatically generated. */
|
|
DirectTransferAtomInit (atoms, 64);
|
|
|
|
/* Now, initialize quarks. */
|
|
resource_quark = XrmPermStringToQuark (compositor.resource_name);
|
|
app_quark = XrmPermStringToQuark (compositor.app_name);
|
|
QString = XrmPermStringToQuark ("String");
|
|
}
|