forked from 12to11/12to11
Implement support for zwp_text_input_manager_v3
* 12to11.c (HandleCmdline): New function. (XLMain): Handle locale, initialize text input and and set up the resource database. * 12to11.man: Document resources and command-line arguments. * Imakefile (SRCS, OBJS): Add text_input.c and text_input.o. (text-input-unstable-v3): New scanner target. * README: Document support for zwp_text_input_manager_v3. * alloc.c (XLMalloc, XLCalloc, XLRealloc): Allow alloc of size 0 to return NULL. * atoms.c (resource_quark, app_quark, QString): New quarks. (XLInitAtoms): Initialize some quarks. * compositor.h (struct _Compositor): Add resource and app names. (struct _RoleFuncs): Add `select_extra_events'. (struct _TextInputFuncs): New structure. * run.c (HandleOneXEvent): Filter events if necessary. * seat.c (AllKeyMask): New define. (input_funcs): New variable. (MakeSeatForDevicePair, NoticeDeviceDisabled): Always assign a single seat the role of "text input seat". (ClearFocusSurface, SetFocusSurface): Call input method hooks. (HackKeyboardModifiers): New function. (DispatchKey): Ignore repeated key events. (XLSeatGetFocus): New function. (XLSeatSetTextInputFuncs, XLSeatGetKeyboardDevice) (XLSeatGetInputMethodSeat, XLSeatDispatchCoreKeyEvent): New function. * surface.c (XLSurfaceSelectExtraEvents): New function. * xdg_surface.c (DefaultEventMask): Add core event mask here. (XLHandleXEventForXdgSurfaces): Handle core key events. (Commit, NoteBounds): Improve debug code. (SelectExtraEvents): New function. (XLGetXdgSurface, XLXdgRoleSetBoundsSize): Improve debug code. (XLInitXdgSurfaces): Reduce size of assoc table. * xdg_toplevel.c (SendConfigure, SendDecorationConfigure, Map) (HandleConfigureEvent, SetMode, UnsetMode): Avoid sending decoration configure before initial commit.
This commit is contained in:
parent
46aa84e4e5
commit
c190ead122
12 changed files with 526 additions and 49 deletions
79
12to11.c
79
12to11.c
|
@ -19,8 +19,10 @@ along with 12to11. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <locale.h>
|
||||||
|
|
||||||
#include "compositor.h"
|
#include "compositor.h"
|
||||||
|
|
||||||
|
@ -62,6 +64,71 @@ DetermineServerTime (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
HandleCmdline (int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Set the default resource and class names. */
|
||||||
|
compositor.resource_name = "12to11";
|
||||||
|
compositor.app_name = "12to11";
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
/* There are no arguments to handle. */
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Determine the instance name based on the executable. First,
|
||||||
|
remove any leading directory separator from argv[0]. */
|
||||||
|
compositor.app_name = strrchr (argv[0], '/');
|
||||||
|
|
||||||
|
/* If no directory separator was present, just use it. */
|
||||||
|
if (!compositor.app_name)
|
||||||
|
compositor.app_name = argv[0];
|
||||||
|
else
|
||||||
|
/* Otherwise, strip the trailing '/'. */
|
||||||
|
compositor.app_name = compositor.app_name + 1;
|
||||||
|
|
||||||
|
for (i = 1; i < argc; ++i)
|
||||||
|
{
|
||||||
|
if (!strcmp (argv[i], "-help"))
|
||||||
|
{
|
||||||
|
print_usage:
|
||||||
|
fprintf (stderr,
|
||||||
|
"usage: %s [-name name] [-class class]\n",
|
||||||
|
argv[0]);
|
||||||
|
exit (!strcmp (argv[i], "-help") ? 0 : 1);
|
||||||
|
}
|
||||||
|
else if (!strcmp (argv[i], "-class"))
|
||||||
|
{
|
||||||
|
if (i + 1 >= argc)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s: option -class requires a value\n",
|
||||||
|
argv[0]);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
compositor.resource_name = argv[++i];
|
||||||
|
}
|
||||||
|
else if (!strcmp (argv[i], "-name"))
|
||||||
|
{
|
||||||
|
if (i + 1 >= argc)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s: option -name requires a value\n",
|
||||||
|
argv[0]);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
compositor.app_name = argv[++i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s: bad command line option \"%s\"\n",
|
||||||
|
argv[0], argv[1]);
|
||||||
|
goto print_usage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
XLMain (int argc, char **argv)
|
XLMain (int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
@ -69,6 +136,9 @@ XLMain (int argc, char **argv)
|
||||||
struct wl_display *wl_display;
|
struct wl_display *wl_display;
|
||||||
const char *socket;
|
const char *socket;
|
||||||
|
|
||||||
|
/* Set the locale. */
|
||||||
|
setlocale (LC_ALL, "");
|
||||||
|
|
||||||
dpy = XOpenDisplay (NULL);
|
dpy = XOpenDisplay (NULL);
|
||||||
wl_display = wl_display_create ();
|
wl_display = wl_display_create ();
|
||||||
|
|
||||||
|
@ -86,6 +156,14 @@ XLMain (int argc, char **argv)
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Call XGetDefault with some dummy values to have the resource
|
||||||
|
database set up. */
|
||||||
|
XrmInitialize ();
|
||||||
|
XGetDefault (dpy, "dummmy", "value");
|
||||||
|
|
||||||
|
/* Parse command-line arguments. */
|
||||||
|
HandleCmdline (argc, argv);
|
||||||
|
|
||||||
compositor.display = dpy;
|
compositor.display = dpy;
|
||||||
compositor.conn = XGetXCBConnection (dpy);
|
compositor.conn = XGetXCBConnection (dpy);
|
||||||
compositor.wl_display = wl_display;
|
compositor.wl_display = wl_display;
|
||||||
|
@ -124,6 +202,7 @@ XLMain (int argc, char **argv)
|
||||||
XLInitExplicitSynchronization ();
|
XLInitExplicitSynchronization ();
|
||||||
XLInitWpViewporter ();
|
XLInitWpViewporter ();
|
||||||
XLInitDecoration ();
|
XLInitDecoration ();
|
||||||
|
XLInitTextInput ();
|
||||||
/* This has to come after the rest of the initialization. */
|
/* This has to come after the rest of the initialization. */
|
||||||
DetermineServerTime ();
|
DetermineServerTime ();
|
||||||
XLRunCompositor ();
|
XLRunCompositor ();
|
||||||
|
|
94
12to11.man
94
12to11.man
|
@ -3,12 +3,102 @@
|
||||||
12to11 - Wayland to X protocol translator
|
12to11 - Wayland to X protocol translator
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B 12to11
|
.B 12to11
|
||||||
|
[\-\fIclass\fP class] [\-\fIname\fP name]
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.I 12to11
|
.I 12to11
|
||||||
starts a Wayland compositor on the next available socket;
|
starts a Wayland compositor on the next available socket;
|
||||||
Wayland programs will then be displayed through the X server.
|
Wayland programs will then be displayed through the X server.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
None.
|
Some X Toolkit library-style command-line arguments are also accepted,
|
||||||
|
despite the protocol translator being implemented without using a
|
||||||
|
toolkit. These options are:
|
||||||
|
.TP 8
|
||||||
|
.B \-class \fIclass\fP
|
||||||
|
This option specifies the resource class under which resources are to
|
||||||
|
be obtained. When not set, it defaults to the string ``12to11''. The
|
||||||
|
resource class and name used by the protocol translator are \fInot\fP
|
||||||
|
set as the
|
||||||
|
.B WM_CLASS
|
||||||
|
property on windows created by the protocol translator; instead, those
|
||||||
|
windows get the classes and names assigned to them by their individual
|
||||||
|
Wayland clients.
|
||||||
|
.TP 8
|
||||||
|
.B \-name \fIname\fP
|
||||||
|
This option specifies the instance name under which resources are to
|
||||||
|
be obtained. When not set, it defaults to the executable file name.
|
||||||
|
.TP 8
|
||||||
|
.B \-help\fP
|
||||||
|
This option causes the protocol translator to print a message
|
||||||
|
describing options it accepts. The protocol translator will then exit
|
||||||
|
after printing the message.
|
||||||
|
.SH RESOURCES
|
||||||
|
\fI12to11\fP understands some resource names and classes that can be
|
||||||
|
used to specify various settings that affect its behavior. Those
|
||||||
|
resources are listed below:
|
||||||
|
.TP 8
|
||||||
|
.B ximFont\fP (class \fBXimFont\fP)
|
||||||
|
Specifies the font to be used for displaying the preedit or status
|
||||||
|
areas of an input method.
|
||||||
|
.IP
|
||||||
|
In many input methods, the preedit (a.k.a composition or
|
||||||
|
preconversion) string and/or a status window is displayed on screen
|
||||||
|
while typing by the input method server. The client is supposed to
|
||||||
|
determine the font used by the input method server to display --
|
||||||
|
however, the Wayland protocol does not allow Wayland clients to
|
||||||
|
specify that themselves, so the protocol translator has to do that by
|
||||||
|
itself.
|
||||||
|
.TP
|
||||||
|
.B ximStyles\fP (class \fBXimStyles\fP)
|
||||||
|
Specifies the default input method styles used by the protocol
|
||||||
|
translator.
|
||||||
|
.IP
|
||||||
|
X input methods can support different editing styles, which affect how
|
||||||
|
preconversion and status text is displayed while typing. These styles
|
||||||
|
are named:
|
||||||
|
.TP
|
||||||
|
.I overTheSpot
|
||||||
|
In ``over the spot'', the preedit string is displayed in a window
|
||||||
|
created by the input method at a location specified by the Wayland
|
||||||
|
client, typically the text insertion point.
|
||||||
|
.TP
|
||||||
|
.I offTheSpot
|
||||||
|
In ``off the spot'', the preedit string is displayed in a window
|
||||||
|
created by the input method at some location away from the text
|
||||||
|
insertion point. Often, this type of window is placed at the bottom
|
||||||
|
of the preedit window.
|
||||||
|
.TP
|
||||||
|
.I rootWindow
|
||||||
|
In the ``root window'' editing style, the preedit string is displayed
|
||||||
|
in a popup window created by the input method.
|
||||||
|
.TP
|
||||||
|
.I onTheSpot
|
||||||
|
In the ``on the spot'' editing style, the preedit string is displayed
|
||||||
|
inside the text itself by the Wayland client.
|
||||||
|
.PP
|
||||||
|
Not all input methods support all editing styles. In the real world,
|
||||||
|
most only support one or two of the styles listed above. The protocol
|
||||||
|
translator will search for a style supported by the input method when
|
||||||
|
initializing input method support. The \fBximStyles\fP resource is
|
||||||
|
used to control the order in which the protocol translator searches
|
||||||
|
for input styles, and should be a comma separated list of input names,
|
||||||
|
which are searched in left-to-right order. For example,
|
||||||
|
.PP
|
||||||
|
.in +4
|
||||||
|
.EX
|
||||||
|
\fBoverTheSpot,rootWindow\fP
|
||||||
|
.EE
|
||||||
|
.in
|
||||||
|
.PP
|
||||||
|
will result in the protocol translator searching for the ``over the
|
||||||
|
spot'' input style, and if that is not present, the ``root window''
|
||||||
|
style. Whitespace must not be present inside the comma-separated
|
||||||
|
list. When \fBximStyles\fP is not specified, it defaults to:
|
||||||
|
.PP
|
||||||
|
.in +4
|
||||||
|
.EX
|
||||||
|
\fBoverTheSpot,offTheSpot,rootWindow,onTheSpot\fP
|
||||||
|
.EE
|
||||||
|
.in
|
||||||
.SH ENVIRONMENT
|
.SH ENVIRONMENT
|
||||||
Several environment variables exist that modify the behavior of the
|
Several environment variables exist that modify the behavior of the
|
||||||
protocol translator in one way or another. Most of these are used for
|
protocol translator in one way or another. Most of these are used for
|
||||||
|
@ -99,6 +189,6 @@ and
|
||||||
window manager hints will result in Wayland programs running
|
window manager hints will result in Wayland programs running
|
||||||
incorrectly.
|
incorrectly.
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
X(1), Xorg(1)
|
X(7), Xorg(1)
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
Various contributors.
|
Various contributors.
|
||||||
|
|
|
@ -21,7 +21,7 @@ SRCS = 12to11.c run.c alloc.c fns.c output.c compositor.c \
|
||||||
dmabuf.c buffer.c select.c xdata.c xsettings.c dnd.c \
|
dmabuf.c buffer.c select.c xdata.c xsettings.c dnd.c \
|
||||||
icon_surface.c primary_selection.c renderer.c \
|
icon_surface.c primary_selection.c renderer.c \
|
||||||
picture_renderer.c explicit_synchronization.c transform.c \
|
picture_renderer.c explicit_synchronization.c transform.c \
|
||||||
wp_viewporter.c decoration.c
|
wp_viewporter.c decoration.c text_input.c
|
||||||
|
|
||||||
OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \
|
OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \
|
||||||
surface.o region.o shm.o atoms.o subcompositor.o positioner.o \
|
surface.o region.o shm.o atoms.o subcompositor.o positioner.o \
|
||||||
|
@ -30,7 +30,7 @@ OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \
|
||||||
dmabuf.o buffer.o select.o xdata.o xsettings.o dnd.o \
|
dmabuf.o buffer.o select.o xdata.o xsettings.o dnd.o \
|
||||||
icon_surface.o primary_selection.o renderer.o \
|
icon_surface.o primary_selection.o renderer.o \
|
||||||
picture_renderer.o explicit_synchronization.o transform.o \
|
picture_renderer.o explicit_synchronization.o transform.o \
|
||||||
wp_viewporter.o decoration.o
|
wp_viewporter.o decoration.o text_input.o
|
||||||
|
|
||||||
GENHEADERS = transfer_atoms.h
|
GENHEADERS = transfer_atoms.h
|
||||||
|
|
||||||
|
@ -111,6 +111,7 @@ ScannerTarget(primary-selection-unstable-v1)
|
||||||
ScannerTarget(linux-explicit-synchronization-unstable-v1)
|
ScannerTarget(linux-explicit-synchronization-unstable-v1)
|
||||||
ScannerTarget(viewporter)
|
ScannerTarget(viewporter)
|
||||||
ScannerTarget(xdg-decoration-unstable-v1)
|
ScannerTarget(xdg-decoration-unstable-v1)
|
||||||
|
ScannerTarget(text-input-unstable-v3)
|
||||||
|
|
||||||
/* Make OBJS depend on scanner headers, and depend on both them and SRCS. */
|
/* Make OBJS depend on scanner headers, and depend on both them and SRCS. */
|
||||||
$(OBJS): $(GENHEADERS)
|
$(OBJS): $(GENHEADERS)
|
||||||
|
|
1
README
1
README
|
@ -66,6 +66,7 @@ complete degree:
|
||||||
'zwp_primary_selection_device_manager_v1', version: 1
|
'zwp_primary_selection_device_manager_v1', version: 1
|
||||||
'wp_viewporter', version: 1
|
'wp_viewporter', version: 1
|
||||||
'zxdg_decoration_manager_v1', version: 1
|
'zxdg_decoration_manager_v1', version: 1
|
||||||
|
'zwp_text_input_manager_v3', version: 1
|
||||||
|
|
||||||
When built with EGL, the following Wayland protocol is also supported:
|
When built with EGL, the following Wayland protocol is also supported:
|
||||||
|
|
||||||
|
|
8
alloc.c
8
alloc.c
|
@ -31,7 +31,7 @@ XLMalloc (size_t size)
|
||||||
|
|
||||||
ptr = malloc (size);
|
ptr = malloc (size);
|
||||||
|
|
||||||
if (!ptr)
|
if (!ptr && size)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "Allocation of %zu bytes failed\n",
|
fprintf (stderr, "Allocation of %zu bytes failed\n",
|
||||||
size);
|
size);
|
||||||
|
@ -54,7 +54,7 @@ XLCalloc (size_t nmemb, size_t size)
|
||||||
|
|
||||||
ptr = calloc (nmemb, size);
|
ptr = calloc (nmemb, size);
|
||||||
|
|
||||||
if (!ptr)
|
if (!ptr && nmemb && size)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "Allocation of %zu * %zu failed\n",
|
fprintf (stderr, "Allocation of %zu * %zu failed\n",
|
||||||
nmemb, size);
|
nmemb, size);
|
||||||
|
@ -96,11 +96,13 @@ XLRealloc (void *ptr, size_t size)
|
||||||
|
|
||||||
ptr = realloc (ptr, size);
|
ptr = realloc (ptr, size);
|
||||||
|
|
||||||
if (!ptr)
|
if (size && !ptr)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "Reallocation of %zu bytes failed\n", size);
|
fprintf (stderr, "Reallocation of %zu bytes failed\n", size);
|
||||||
abort ();
|
abort ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allow realloc to return NULL if size is also NULL. */
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
7
atoms.c
7
atoms.c
|
@ -131,6 +131,8 @@ Atom _NET_WM_OPAQUE_REGION, _XL_BUFFER_RELEASE, _NET_WM_SYNC_REQUEST_COUNTER,
|
||||||
_NET_WM_FRAME_TIMINGS, _NET_WM_BYPASS_COMPOSITOR, WM_STATE,
|
_NET_WM_FRAME_TIMINGS, _NET_WM_BYPASS_COMPOSITOR, WM_STATE,
|
||||||
_NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_MENU, _NET_WM_WINDOW_TYPE_DND;
|
_NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_MENU, _NET_WM_WINDOW_TYPE_DND;
|
||||||
|
|
||||||
|
XrmQuark resource_quark, app_quark, QString;
|
||||||
|
|
||||||
/* Hash table containing atoms. */
|
/* Hash table containing atoms. */
|
||||||
|
|
||||||
static AtomTable atom_table;
|
static AtomTable atom_table;
|
||||||
|
@ -284,4 +286,9 @@ XLInitAtoms (void)
|
||||||
|
|
||||||
/* This is automatically generated. */
|
/* This is automatically generated. */
|
||||||
DirectTransferAtomInit (atoms, 61);
|
DirectTransferAtomInit (atoms, 61);
|
||||||
|
|
||||||
|
/* Now, initialize quarks. */
|
||||||
|
resource_quark = XrmPermStringToQuark (compositor.resource_name);
|
||||||
|
app_quark = XrmPermStringToQuark (compositor.app_name);
|
||||||
|
QString = XrmPermStringToQuark ("String");
|
||||||
}
|
}
|
||||||
|
|
30
compositor.h
30
compositor.h
|
@ -26,6 +26,7 @@ along with 12to11. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
#include <X11/Xlib-xcb.h>
|
#include <X11/Xlib-xcb.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
|
#include <X11/Xresource.h>
|
||||||
|
|
||||||
#include <X11/extensions/Xrandr.h>
|
#include <X11/extensions/Xrandr.h>
|
||||||
#include <X11/extensions/Xrender.h>
|
#include <X11/extensions/Xrender.h>
|
||||||
|
@ -80,6 +81,9 @@ struct _Compositor
|
||||||
|
|
||||||
/* Whether the server time is monotonic. */
|
/* Whether the server time is monotonic. */
|
||||||
Bool server_time_monotonic;
|
Bool server_time_monotonic;
|
||||||
|
|
||||||
|
/* The resource and app names. */
|
||||||
|
const char *resource_name, *app_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Forward declarations from seat.c. */
|
/* Forward declarations from seat.c. */
|
||||||
|
@ -920,6 +924,7 @@ struct _RoleFuncs
|
||||||
void (*parent_rescale) (Surface *, Role *);
|
void (*parent_rescale) (Surface *, Role *);
|
||||||
void (*note_desync_child) (Surface *, Role *);
|
void (*note_desync_child) (Surface *, Role *);
|
||||||
void (*note_child_synced) (Surface *, Role *);
|
void (*note_child_synced) (Surface *, Role *);
|
||||||
|
void (*select_extra_events) (Surface *, Role *, unsigned long);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Role
|
struct _Role
|
||||||
|
@ -966,6 +971,7 @@ extern void XLSurfacePostResize (Surface *, int, int, int, int);
|
||||||
extern void XLSurfaceMoveBy (Surface *, int, int);
|
extern void XLSurfaceMoveBy (Surface *, int, int);
|
||||||
extern Window XLWindowFromSurface (Surface *);
|
extern Window XLWindowFromSurface (Surface *);
|
||||||
extern void XLUpdateSurfaceOutputs (Surface *, int, int, int, int);
|
extern void XLUpdateSurfaceOutputs (Surface *, int, int, int, int);
|
||||||
|
extern void XLSurfaceSelectExtraEvents (Surface *, unsigned long);
|
||||||
|
|
||||||
extern void SurfaceToWindow (Surface *, double, double, double *, double *);
|
extern void SurfaceToWindow (Surface *, double, double, double *, double *);
|
||||||
extern void ScaleToWindow (Surface *, double, double, double *, double *);
|
extern void ScaleToWindow (Surface *, double, double, double *, double *);
|
||||||
|
@ -1008,6 +1014,8 @@ extern Atom _NET_WM_OPAQUE_REGION, _XL_BUFFER_RELEASE,
|
||||||
XdndFinished, _NET_WM_FRAME_TIMINGS, _NET_WM_BYPASS_COMPOSITOR, WM_STATE,
|
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;
|
_NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_MENU, _NET_WM_WINDOW_TYPE_DND;
|
||||||
|
|
||||||
|
extern XrmQuark resource_quark, app_quark, QString;
|
||||||
|
|
||||||
/* This is automatically generated by mime4.awk. */
|
/* This is automatically generated by mime4.awk. */
|
||||||
extern Atom DirectTransferAtoms;
|
extern Atom DirectTransferAtoms;
|
||||||
|
|
||||||
|
@ -1247,6 +1255,22 @@ extern void XLDataDeviceSendMotion (Seat *, Surface *, double, double, Time);
|
||||||
extern void XLDataDeviceSendLeave (Seat *, Surface *, DataSource *);
|
extern void XLDataDeviceSendLeave (Seat *, Surface *, DataSource *);
|
||||||
extern void XLDataDeviceSendDrop (Seat *, Surface *);
|
extern void XLDataDeviceSendDrop (Seat *, Surface *);
|
||||||
|
|
||||||
|
/* Defined in text_input.h. */
|
||||||
|
|
||||||
|
typedef struct _TextInputFuncs TextInputFuncs;
|
||||||
|
|
||||||
|
struct _TextInputFuncs
|
||||||
|
{
|
||||||
|
void (*focus_in) (Seat *, Surface *);
|
||||||
|
void (*focus_out) (Seat *);
|
||||||
|
|
||||||
|
/* The last argument is actually an XIDeviceEvent *. */
|
||||||
|
Bool (*filter_input) (Seat *, Surface *, void *);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void XLTextInputDispatchCoreEvent (Surface *, XEvent *);
|
||||||
|
extern void XLInitTextInput (void);
|
||||||
|
|
||||||
/* Defined in seat.c. */
|
/* Defined in seat.c. */
|
||||||
|
|
||||||
extern int xi2_opcode;
|
extern int xi2_opcode;
|
||||||
|
@ -1274,6 +1298,7 @@ extern DataDevice *XLSeatGetDataDevice (Seat *);
|
||||||
extern void XLSeatSetDataDevice (Seat *, DataDevice *);
|
extern void XLSeatSetDataDevice (Seat *, DataDevice *);
|
||||||
extern Bool XLSeatIsInert (Seat *);
|
extern Bool XLSeatIsInert (Seat *);
|
||||||
extern Bool XLSeatIsClientFocused (Seat *, struct wl_client *);
|
extern Bool XLSeatIsClientFocused (Seat *, struct wl_client *);
|
||||||
|
extern Surface *XLSeatGetFocus (Seat *);
|
||||||
extern void XLSeatShowWindowMenu (Seat *, Surface *, int, int);
|
extern void XLSeatShowWindowMenu (Seat *, Surface *, int, int);
|
||||||
extern Time XLSeatGetLastUserTime (Seat *);
|
extern Time XLSeatGetLastUserTime (Seat *);
|
||||||
extern void XLSeatBeginDrag (Seat *, DataSource *, Surface *,
|
extern void XLSeatBeginDrag (Seat *, DataSource *, Surface *,
|
||||||
|
@ -1284,6 +1309,11 @@ extern void *XLSeatAddModifierCallback (Seat *, void (*) (unsigned int, void *),
|
||||||
extern void XLSeatRemoveModifierCallback (void *);
|
extern void XLSeatRemoveModifierCallback (void *);
|
||||||
extern unsigned int XLSeatGetEffectiveModifiers (Seat *);
|
extern unsigned int XLSeatGetEffectiveModifiers (Seat *);
|
||||||
extern Bool XLSeatResizeInProgress (Seat *);
|
extern Bool XLSeatResizeInProgress (Seat *);
|
||||||
|
extern void XLSeatSetTextInputFuncs (TextInputFuncs *);
|
||||||
|
extern int XLSeatGetKeyboardDevice (Seat *);
|
||||||
|
extern Seat *XLSeatGetInputMethodSeat (void);
|
||||||
|
extern void XLSeatDispatchCoreKeyEvent (Seat *, Surface *, XEvent *,
|
||||||
|
KeySym);
|
||||||
|
|
||||||
extern Cursor InitDefaultCursor (void);
|
extern Cursor InitDefaultCursor (void);
|
||||||
|
|
||||||
|
|
6
run.c
6
run.c
|
@ -130,6 +130,12 @@ HandleOneXEvent (XEvent *event)
|
||||||
{
|
{
|
||||||
XLHandleOneXEventForDnd (event);
|
XLHandleOneXEventForDnd (event);
|
||||||
|
|
||||||
|
/* Filter all non-GenericEvents through the input method
|
||||||
|
infrastructure. */
|
||||||
|
if (event->type != GenericEvent
|
||||||
|
&& XFilterEvent (event, event->xany.window))
|
||||||
|
return;
|
||||||
|
|
||||||
if (XLHandleXEventForXdgSurfaces (event))
|
if (XLHandleXEventForXdgSurfaces (event))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
181
seat.c
181
seat.c
|
@ -75,12 +75,18 @@ static XLAssocTable *devices;
|
||||||
|
|
||||||
XLList *live_seats;
|
XLList *live_seats;
|
||||||
|
|
||||||
|
/* This is a mask of all keyboard state. */
|
||||||
|
#define AllKeyMask \
|
||||||
|
(ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | Mod3Mask \
|
||||||
|
| Mod4Mask)
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
IsInert = 1,
|
IsInert = 1,
|
||||||
IsWindowMenuShown = (1 << 2),
|
IsWindowMenuShown = (1 << 2),
|
||||||
IsDragging = (1 << 3),
|
IsDragging = (1 << 3),
|
||||||
IsDropped = (1 << 4),
|
IsDropped = (1 << 4),
|
||||||
|
IsTextInputSeat = (1 << 5),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -533,6 +539,9 @@ struct _DeviceInfo
|
||||||
#define MaskLen(event) \
|
#define MaskLen(event) \
|
||||||
(((event) >> 3) + 1)
|
(((event) >> 3) + 1)
|
||||||
|
|
||||||
|
/* Text input functions. */
|
||||||
|
static TextInputFuncs *input_funcs;
|
||||||
|
|
||||||
#define CursorFromRole(role) ((SeatCursor *) (role))
|
#define CursorFromRole(role) ((SeatCursor *) (role))
|
||||||
|
|
||||||
/* Subcompositor targets used inside cursor subframes. */
|
/* Subcompositor targets used inside cursor subframes. */
|
||||||
|
@ -1786,6 +1795,10 @@ MakeSeatForDevicePair (int master_keyboard, int master_pointer,
|
||||||
XLMakeAssoc (seats, master_keyboard, seat);
|
XLMakeAssoc (seats, master_keyboard, seat);
|
||||||
XLMakeAssoc (seats, master_pointer, seat);
|
XLMakeAssoc (seats, master_pointer, seat);
|
||||||
|
|
||||||
|
if (!live_seats)
|
||||||
|
/* This is the first seat; make it the input seat. */
|
||||||
|
seat->flags |= IsTextInputSeat;
|
||||||
|
|
||||||
live_seats = XLListPrepend (live_seats, seat);
|
live_seats = XLListPrepend (live_seats, seat);
|
||||||
|
|
||||||
/* Now update the seat state from the X server. */
|
/* Now update the seat state from the X server. */
|
||||||
|
@ -2076,7 +2089,7 @@ RunDestroyListeners (Seat *seat)
|
||||||
static void
|
static void
|
||||||
NoticeDeviceDisabled (int deviceid)
|
NoticeDeviceDisabled (int deviceid)
|
||||||
{
|
{
|
||||||
Seat *seat;
|
Seat *seat, *new;
|
||||||
DeviceInfo *info;
|
DeviceInfo *info;
|
||||||
|
|
||||||
/* First, see if there is any deviceinfo related to the disabled
|
/* First, see if there is any deviceinfo related to the disabled
|
||||||
|
@ -2124,6 +2137,18 @@ NoticeDeviceDisabled (int deviceid)
|
||||||
|
|
||||||
wl_global_destroy (seat->global);
|
wl_global_destroy (seat->global);
|
||||||
|
|
||||||
|
/* If it was the input seat, then find a new seat to take its
|
||||||
|
place. */
|
||||||
|
if (seat->flags & IsTextInputSeat
|
||||||
|
&& live_seats)
|
||||||
|
{
|
||||||
|
new = live_seats->data;
|
||||||
|
|
||||||
|
/* This results in nondeterministic selection of input
|
||||||
|
seats, and as such can be confusing to the user. */
|
||||||
|
new->flags |= IsTextInputSeat;
|
||||||
|
}
|
||||||
|
|
||||||
/* And release the seat. */
|
/* And release the seat. */
|
||||||
|
|
||||||
ReleaseSeat (seat);
|
ReleaseSeat (seat);
|
||||||
|
@ -2624,6 +2649,12 @@ ClearFocusSurface (void *data)
|
||||||
|
|
||||||
seat->focus_surface = NULL;
|
seat->focus_surface = NULL;
|
||||||
seat->focus_destroy_callback = NULL;
|
seat->focus_destroy_callback = NULL;
|
||||||
|
|
||||||
|
XLPrimarySelectionHandleFocusChange (seat);
|
||||||
|
|
||||||
|
/* Tell any input method about the focus change. */
|
||||||
|
if (input_funcs)
|
||||||
|
input_funcs->focus_out (seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2697,6 +2728,29 @@ SendKeyboardModifiers (Seat *seat, Surface *focus)
|
||||||
UpdateSingleModifiers (seat, keyboard, serial);
|
UpdateSingleModifiers (seat, keyboard, serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
HackKeyboardModifiers (Seat *seat, Surface *focus, int effective,
|
||||||
|
int group)
|
||||||
|
{
|
||||||
|
Keyboard *keyboard;
|
||||||
|
uint32_t serial;
|
||||||
|
SeatClientInfo *info;
|
||||||
|
|
||||||
|
serial = wl_display_next_serial (compositor.wl_display);
|
||||||
|
info = ClientInfoForResource (seat, focus->resource);
|
||||||
|
|
||||||
|
if (!info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
keyboard = info->keyboards.next;
|
||||||
|
|
||||||
|
for (; keyboard != &info->keyboards; keyboard = keyboard->next)
|
||||||
|
/* It is wrong to send the new modifiers in seat->based, but I
|
||||||
|
don't know anything better. */
|
||||||
|
wl_keyboard_send_modifiers (keyboard->resource, serial,
|
||||||
|
effective, 0, 0, group);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
SendUpdatedModifiers (Seat *seat)
|
SendUpdatedModifiers (Seat *seat)
|
||||||
{
|
{
|
||||||
|
@ -2758,6 +2812,10 @@ SetFocusSurface (Seat *seat, Surface *focus)
|
||||||
XLSurfaceCancelRunOnFree (seat->focus_destroy_callback);
|
XLSurfaceCancelRunOnFree (seat->focus_destroy_callback);
|
||||||
seat->focus_destroy_callback = NULL;
|
seat->focus_destroy_callback = NULL;
|
||||||
seat->focus_surface = NULL;
|
seat->focus_surface = NULL;
|
||||||
|
|
||||||
|
if (input_funcs)
|
||||||
|
/* Tell any input method about the change. */
|
||||||
|
input_funcs->focus_out (seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!focus)
|
if (!focus)
|
||||||
|
@ -2768,6 +2826,10 @@ SetFocusSurface (Seat *seat, Surface *focus)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (input_funcs)
|
||||||
|
/* Tell any input method about the change. */
|
||||||
|
input_funcs->focus_in (seat, focus);
|
||||||
|
|
||||||
seat->focus_surface = focus;
|
seat->focus_surface = focus;
|
||||||
seat->focus_destroy_callback
|
seat->focus_destroy_callback
|
||||||
= XLSurfaceRunOnFree (focus, ClearFocusSurface, seat);
|
= XLSurfaceRunOnFree (focus, ClearFocusSurface, seat);
|
||||||
|
@ -3971,6 +4033,17 @@ DispatchKey (XIDeviceEvent *xev)
|
||||||
|
|
||||||
if (seat->focus_surface)
|
if (seat->focus_surface)
|
||||||
{
|
{
|
||||||
|
if (input_funcs
|
||||||
|
&& seat->flags & IsTextInputSeat
|
||||||
|
&& input_funcs->filter_input (seat, seat->focus_surface,
|
||||||
|
xev))
|
||||||
|
/* The input method decided to filter the key. */
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Ignore repeated keys. */
|
||||||
|
if (xev->flags & XIKeyRepeat)
|
||||||
|
return;
|
||||||
|
|
||||||
if (xev->evtype == XI_KeyPress)
|
if (xev->evtype == XI_KeyPress)
|
||||||
SendKeyboardKey (seat, seat->focus_surface,
|
SendKeyboardKey (seat, seat->focus_surface,
|
||||||
xev->time, WaylandKeycode (xev->detail),
|
xev->time, WaylandKeycode (xev->detail),
|
||||||
|
@ -4799,6 +4872,12 @@ XLSeatIsClientFocused (Seat *seat, struct wl_client *client)
|
||||||
return client == surface_client;
|
return client == surface_client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Surface *
|
||||||
|
XLSeatGetFocus (Seat *seat)
|
||||||
|
{
|
||||||
|
return seat->focus_surface;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
XLSeatShowWindowMenu (Seat *seat, Surface *surface, int root_x,
|
XLSeatShowWindowMenu (Seat *seat, Surface *surface, int root_x,
|
||||||
int root_y)
|
int root_y)
|
||||||
|
@ -5272,3 +5351,103 @@ XLSeatResizeInProgress (Seat *seat)
|
||||||
{
|
{
|
||||||
return seat->resize_in_progress;
|
return seat->resize_in_progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
XLSeatSetTextInputFuncs (TextInputFuncs *funcs)
|
||||||
|
{
|
||||||
|
input_funcs = funcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
XLSeatGetKeyboardDevice (Seat *seat)
|
||||||
|
{
|
||||||
|
return seat->master_keyboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
Seat *
|
||||||
|
XLSeatGetInputMethodSeat (void)
|
||||||
|
{
|
||||||
|
XLList *list;
|
||||||
|
Seat *seat;
|
||||||
|
|
||||||
|
for (list = live_seats; list; list = list->next)
|
||||||
|
{
|
||||||
|
seat = list->data;
|
||||||
|
|
||||||
|
if (seat->flags & IsTextInputSeat)
|
||||||
|
return seat;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
XLSeatDispatchCoreKeyEvent (Seat *seat, Surface *surface, XEvent *event,
|
||||||
|
KeySym keysym)
|
||||||
|
{
|
||||||
|
unsigned int effective;
|
||||||
|
unsigned int state, group;
|
||||||
|
unsigned int mods_return;
|
||||||
|
KeyCode keycode;
|
||||||
|
KeySym sym_return;
|
||||||
|
|
||||||
|
/* Dispatch a core event generated by an input method to SEAT. If
|
||||||
|
SURFACE is no longer the focus surface, refrain from doing
|
||||||
|
anything. If a keycode can be found for KEYSYM, use that
|
||||||
|
keycode. */
|
||||||
|
|
||||||
|
if (surface != seat->focus_surface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Get the group and state of the key event. */
|
||||||
|
group = event->xkey.state >> 13;
|
||||||
|
state = event->xkey.state & AllKeyMask;
|
||||||
|
|
||||||
|
/* Get the effective state of the seat. */
|
||||||
|
effective = seat->base | seat->latched | seat->locked;
|
||||||
|
|
||||||
|
/* Determine what keycode to use. If a keysym was provided, try to
|
||||||
|
find a corresponding keycode. */
|
||||||
|
|
||||||
|
if (keysym)
|
||||||
|
{
|
||||||
|
/* If looking up the event keycode also results in the keysym,
|
||||||
|
then just use the keycode specified in the event. */
|
||||||
|
if (XkbLookupKeySym (compositor.display, event->xkey.keycode,
|
||||||
|
event->xkey.state, &mods_return, &sym_return)
|
||||||
|
&& keysym == sym_return)
|
||||||
|
{
|
||||||
|
keycode = event->xkey.keycode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
keycode = XKeysymToKeycode (compositor.display, keysym);
|
||||||
|
|
||||||
|
/* But if no corresponding keycode could be found, use the
|
||||||
|
keycode provided in the event. */
|
||||||
|
if (!keycode)
|
||||||
|
keycode = event->xkey.keycode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
keycode = event->xkey.keycode;
|
||||||
|
|
||||||
|
if (group != seat->effective_group || state != effective)
|
||||||
|
/* The modifiers in the provided core event are different from
|
||||||
|
what the focus surface was previously sent. Send a new
|
||||||
|
modifier event with the effective state provided in the give
|
||||||
|
core event. */
|
||||||
|
HackKeyboardModifiers (seat, surface, effective, group);
|
||||||
|
|
||||||
|
/* Then send the event. */
|
||||||
|
if (event->xkey.type == KeyPress)
|
||||||
|
SendKeyboardKey (seat, seat->focus_surface, event->xkey.time,
|
||||||
|
WaylandKeycode (keycode),
|
||||||
|
WL_KEYBOARD_KEY_STATE_PRESSED);
|
||||||
|
else
|
||||||
|
SendKeyboardKey (seat, seat->focus_surface, event->xkey.time,
|
||||||
|
WaylandKeycode (keycode),
|
||||||
|
WL_KEYBOARD_KEY_STATE_RELEASED);
|
||||||
|
|
||||||
|
/* Restore the modifiers. */
|
||||||
|
if (group != seat->effective_group || state != effective)
|
||||||
|
SendKeyboardModifiers (seat, surface);
|
||||||
|
}
|
||||||
|
|
15
surface.c
15
surface.c
|
@ -1734,6 +1734,21 @@ XLSurfaceMoveBy (Surface *surface, int west, int north)
|
||||||
west, north);
|
west, north);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
XLSurfaceSelectExtraEvents (Surface *surface, unsigned long event_mask)
|
||||||
|
{
|
||||||
|
if (!surface->role
|
||||||
|
|| !surface->role->funcs.select_extra_events)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Note that this need only be implemented for surfaces that can get
|
||||||
|
the input focus. */
|
||||||
|
surface->role->funcs.select_extra_events (surface, surface->role,
|
||||||
|
event_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* The following functions convert from window to surface
|
/* The following functions convert from window to surface
|
||||||
coordinates and vice versa:
|
coordinates and vice versa:
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,10 @@ along with 12to11. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
#define XdgRoleFromRole(role) ((XdgRole *) (role))
|
#define XdgRoleFromRole(role) ((XdgRole *) (role))
|
||||||
|
|
||||||
|
/* This is the default core event mask used by our windows. */
|
||||||
|
#define DefaultEventMask \
|
||||||
|
(ExposureMask | StructureNotifyMask | PropertyChangeMask)
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
StatePendingFrameCallback = 1,
|
StatePendingFrameCallback = 1,
|
||||||
|
@ -472,6 +476,22 @@ XLHandleXEventForXdgSurfaces (XEvent *event)
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event->type == KeyPress || event->type == KeyRelease)
|
||||||
|
{
|
||||||
|
/* These events are actually sent by the input method library
|
||||||
|
upon receiving XIM_COMMIT messages. */
|
||||||
|
|
||||||
|
role = XLLookUpAssoc (surfaces, event->xkey.window);
|
||||||
|
|
||||||
|
if (role && role->role.surface)
|
||||||
|
{
|
||||||
|
XLTextInputDispatchCoreEvent (role->role.surface, event);
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
window = XLGetGEWindowForSeats (event);
|
window = XLGetGEWindowForSeats (event);
|
||||||
|
|
||||||
if (window != None)
|
if (window != None)
|
||||||
|
@ -685,7 +705,8 @@ Commit (Surface *surface, Role *role)
|
||||||
|
|
||||||
/* This flag means no commit has happened after an
|
/* This flag means no commit has happened after an
|
||||||
ack_configure. */
|
ack_configure. */
|
||||||
if (!(xdg_role->state & StateWaitingForAckConfigure))
|
if (!(xdg_role->state & StateWaitingForAckConfigure)
|
||||||
|
&& xdg_role->state & StateWaitingForAckCommit)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_GEOMETRY_CALCULATION
|
#ifdef DEBUG_GEOMETRY_CALCULATION
|
||||||
fprintf (stderr, "Client aknowledged commit\n");
|
fprintf (stderr, "Client aknowledged commit\n");
|
||||||
|
@ -1131,15 +1152,13 @@ NoteBounds (void *data, int min_x, int min_y,
|
||||||
bounds_width = max_x - min_x + 1;
|
bounds_width = max_x - min_x + 1;
|
||||||
bounds_height = max_y - min_y + 1;
|
bounds_height = max_y - min_y + 1;
|
||||||
|
|
||||||
#ifdef DEBUG_GEOMETRY_CALCULATION
|
|
||||||
fprintf (stderr, "Noticed bounds: %d %d\n", bounds_width, bounds_height);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (role->bounds_width != bounds_width
|
if (role->bounds_width != bounds_width
|
||||||
|| role->bounds_height != bounds_height)
|
|| role->bounds_height != bounds_height)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_GEOMETRY_CALCULATION
|
#ifdef DEBUG_GEOMETRY_CALCULATION
|
||||||
fprintf (stderr, "Resizing to: %d %d\n", bounds_width, bounds_height);
|
fprintf (stderr, "Resizing to: %d %d (from: %d %d)\n",
|
||||||
|
bounds_width, bounds_height, role->bounds_width,
|
||||||
|
role->bounds_height);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (role->impl->funcs.note_window_pre_resize)
|
if (role->impl->funcs.note_window_pre_resize)
|
||||||
|
@ -1357,6 +1376,19 @@ HandleFreeze (void *data)
|
||||||
role->state |= StateMaybeConfigure;
|
role->state |= StateMaybeConfigure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SelectExtraEvents (Surface *surface, Role *role,
|
||||||
|
unsigned long event_mask)
|
||||||
|
{
|
||||||
|
XdgRole *xdg_role;
|
||||||
|
|
||||||
|
xdg_role = XdgRoleFromRole (role);
|
||||||
|
|
||||||
|
/* Select extra events for the input method. */
|
||||||
|
XSelectInput (compositor.display, xdg_role->window,
|
||||||
|
DefaultEventMask | event_mask);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
XLGetXdgSurface (struct wl_client *client, struct wl_resource *resource,
|
XLGetXdgSurface (struct wl_client *client, struct wl_resource *resource,
|
||||||
uint32_t id, struct wl_resource *surface_resource)
|
uint32_t id, struct wl_resource *surface_resource)
|
||||||
|
@ -1431,11 +1463,11 @@ XLGetXdgSurface (struct wl_client *client, struct wl_resource *resource,
|
||||||
role->role.funcs.rescale = Rescale;
|
role->role.funcs.rescale = Rescale;
|
||||||
role->role.funcs.note_desync_child = NoteDesyncChild;
|
role->role.funcs.note_desync_child = NoteDesyncChild;
|
||||||
role->role.funcs.note_child_synced = NoteChildSynced;
|
role->role.funcs.note_child_synced = NoteChildSynced;
|
||||||
|
role->role.funcs.select_extra_events = SelectExtraEvents;
|
||||||
|
|
||||||
attrs.colormap = compositor.colormap;
|
attrs.colormap = compositor.colormap;
|
||||||
attrs.border_pixel = border_pixel;
|
attrs.border_pixel = border_pixel;
|
||||||
attrs.event_mask = (ExposureMask | StructureNotifyMask
|
attrs.event_mask = DefaultEventMask;
|
||||||
| PropertyChangeMask);
|
|
||||||
attrs.cursor = InitDefaultCursor ();
|
attrs.cursor = InitDefaultCursor ();
|
||||||
flags = (CWColormap | CWBorderPixel | CWEventMask
|
flags = (CWColormap | CWBorderPixel | CWEventMask
|
||||||
| CWCursor);
|
| CWCursor);
|
||||||
|
@ -1647,6 +1679,11 @@ XLXdgRoleSetBoundsSize (Role *role, int bounds_width, int bounds_height)
|
||||||
xdg_role->bounds_width = bounds_width;
|
xdg_role->bounds_width = bounds_width;
|
||||||
xdg_role->bounds_height = bounds_height;
|
xdg_role->bounds_height = bounds_height;
|
||||||
|
|
||||||
|
#ifdef DEBUG_GEOMETRY_CALCULATION
|
||||||
|
fprintf (stderr, "Set new bounds size: %d %d\n", bounds_width,
|
||||||
|
bounds_height);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Now, a temporary bounds_width and bounds_height has been
|
/* Now, a temporary bounds_width and bounds_height has been
|
||||||
recorded. This means that if a configure event has not yet been
|
recorded. This means that if a configure event has not yet been
|
||||||
delivered, then any subsequent SubcompositorUpdate will cause
|
delivered, then any subsequent SubcompositorUpdate will cause
|
||||||
|
@ -1857,7 +1894,7 @@ XLInitXdgSurfaces (void)
|
||||||
XColor alloc;
|
XColor alloc;
|
||||||
int shape_minor, shape_major, shape_error;
|
int shape_minor, shape_major, shape_error;
|
||||||
|
|
||||||
surfaces = XLCreateAssocTable (2048);
|
surfaces = XLCreateAssocTable (1024);
|
||||||
|
|
||||||
alloc.red = 0;
|
alloc.red = 0;
|
||||||
alloc.green = 65535;
|
alloc.green = 65535;
|
||||||
|
|
|
@ -40,15 +40,17 @@ typedef enum _DecorationMode DecorationMode;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
StateIsMapped = 1,
|
StateIsMapped = 1,
|
||||||
StateMissingState = (1 << 1),
|
StateMissingState = (1 << 1),
|
||||||
StatePendingMaxSize = (1 << 2),
|
StatePendingMaxSize = (1 << 2),
|
||||||
StatePendingMinSize = (1 << 3),
|
StatePendingMinSize = (1 << 3),
|
||||||
StatePendingAckMovement = (1 << 4),
|
StatePendingAckMovement = (1 << 4),
|
||||||
StatePendingResize = (1 << 5),
|
StatePendingResize = (1 << 5),
|
||||||
StatePendingConfigureSize = (1 << 6),
|
StatePendingConfigureSize = (1 << 6),
|
||||||
StatePendingConfigureStates = (1 << 7),
|
StatePendingConfigureStates = (1 << 7),
|
||||||
StateDecorationModeDirty = (1 << 8),
|
StateDecorationModeDirty = (1 << 8),
|
||||||
|
StateEverMapped = (1 << 9),
|
||||||
|
StateNeedDecorationConfigure = (1 << 10),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -370,6 +372,27 @@ AddState (XdgToplevel *toplevel, uint32_t state)
|
||||||
*data = state;
|
*data = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SendDecorationConfigure1 (XdgToplevel *toplevel)
|
||||||
|
{
|
||||||
|
#define ServerSide ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE
|
||||||
|
#define ClientSide ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE
|
||||||
|
|
||||||
|
if (toplevel->decor == DecorationModeClient)
|
||||||
|
zxdg_toplevel_decoration_v1_send_configure (toplevel->decoration->resource,
|
||||||
|
ClientSide);
|
||||||
|
else
|
||||||
|
zxdg_toplevel_decoration_v1_send_configure (toplevel->decoration->resource,
|
||||||
|
ServerSide);
|
||||||
|
|
||||||
|
#undef ServerSide
|
||||||
|
#undef ClientSide
|
||||||
|
|
||||||
|
/* This means that the decoration should be reapplied upon the next
|
||||||
|
commit. */
|
||||||
|
toplevel->state |= StateDecorationModeDirty;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
SendConfigure (XdgToplevel *toplevel, unsigned int width,
|
SendConfigure (XdgToplevel *toplevel, unsigned int width,
|
||||||
unsigned int height)
|
unsigned int height)
|
||||||
|
@ -380,6 +403,15 @@ SendConfigure (XdgToplevel *toplevel, unsigned int width,
|
||||||
xdg_toplevel_send_configure (toplevel->resource, width, height,
|
xdg_toplevel_send_configure (toplevel->resource, width, height,
|
||||||
&toplevel->states);
|
&toplevel->states);
|
||||||
|
|
||||||
|
/* If a toplevel decoration resource is created and
|
||||||
|
SetMode/UnsetMode is called before the initial toplevel commit,
|
||||||
|
then the toplevel decoration mode must be sent here instead. */
|
||||||
|
|
||||||
|
if (toplevel->state & StateNeedDecorationConfigure
|
||||||
|
&& toplevel->decoration)
|
||||||
|
SendDecorationConfigure1 (toplevel);
|
||||||
|
toplevel->state &= ~StateNeedDecorationConfigure;
|
||||||
|
|
||||||
XLXdgRoleSendConfigure (toplevel->role, serial);
|
XLXdgRoleSendConfigure (toplevel->role, serial);
|
||||||
|
|
||||||
toplevel->conf_reply = True;
|
toplevel->conf_reply = True;
|
||||||
|
@ -396,27 +428,11 @@ SendDecorationConfigure (XdgToplevel *toplevel)
|
||||||
|
|
||||||
serial = wl_display_next_serial (compositor.wl_display);
|
serial = wl_display_next_serial (compositor.wl_display);
|
||||||
|
|
||||||
#define ServerSide ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE
|
SendDecorationConfigure1 (toplevel);
|
||||||
#define ClientSide ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE
|
|
||||||
|
|
||||||
if (toplevel->decor == DecorationModeClient)
|
|
||||||
zxdg_toplevel_decoration_v1_send_configure (toplevel->decoration->resource,
|
|
||||||
ClientSide);
|
|
||||||
else
|
|
||||||
zxdg_toplevel_decoration_v1_send_configure (toplevel->decoration->resource,
|
|
||||||
ServerSide);
|
|
||||||
|
|
||||||
#undef ServerSide
|
|
||||||
#undef ClientSide
|
|
||||||
|
|
||||||
XLXdgRoleSendConfigure (toplevel->role, serial);
|
XLXdgRoleSendConfigure (toplevel->role, serial);
|
||||||
|
|
||||||
toplevel->conf_reply = True;
|
toplevel->conf_reply = True;
|
||||||
toplevel->conf_serial = serial;
|
toplevel->conf_serial = serial;
|
||||||
|
|
||||||
/* This means that the decoration should be reapplied upon the next
|
|
||||||
commit. */
|
|
||||||
toplevel->state |= StateDecorationModeDirty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Forward declaration. */
|
/* Forward declaration. */
|
||||||
|
@ -1081,7 +1097,7 @@ Map (XdgToplevel *toplevel)
|
||||||
at this point. */
|
at this point. */
|
||||||
SubcompositorGarbage (XLSubcompositorFromXdgRole (toplevel->role));
|
SubcompositorGarbage (XLSubcompositorFromXdgRole (toplevel->role));
|
||||||
|
|
||||||
toplevel->state |= StateIsMapped | StateMissingState;
|
toplevel->state |= StateIsMapped | StateMissingState | StateEverMapped;
|
||||||
|
|
||||||
/* Update the width and height from the xdg_surface bounds. */
|
/* Update the width and height from the xdg_surface bounds. */
|
||||||
toplevel->width = XLXdgRoleGetWidth (toplevel->role);
|
toplevel->width = XLXdgRoleGetWidth (toplevel->role);
|
||||||
|
@ -1329,6 +1345,10 @@ HandleConfigureEvent (XdgToplevel *toplevel, XEvent *event)
|
||||||
event->xconfigure.height))
|
event->xconfigure.height))
|
||||||
WriteStates (toplevel);
|
WriteStates (toplevel);
|
||||||
|
|
||||||
|
/* Set toplevel->width and toplevel->height correctly. */
|
||||||
|
toplevel->width = event->xconfigure.width;
|
||||||
|
toplevel->height = event->xconfigure.height;
|
||||||
|
|
||||||
/* Also set the bounds width and height to avoid resizing the
|
/* Also set the bounds width and height to avoid resizing the
|
||||||
window. */
|
window. */
|
||||||
XLXdgRoleSetBoundsSize (toplevel->role,
|
XLXdgRoleSetBoundsSize (toplevel->role,
|
||||||
|
@ -1345,9 +1365,8 @@ HandleConfigureEvent (XdgToplevel *toplevel, XEvent *event)
|
||||||
SendConfigure (toplevel, width, height);
|
SendConfigure (toplevel, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set toplevel->width and toplevel->height correctly. */
|
/* Now set toplevel->configure_width and
|
||||||
toplevel->width = event->xconfigure.width;
|
toplevel->configure_height. */
|
||||||
toplevel->height = event->xconfigure.height;
|
|
||||||
toplevel->configure_width = toplevel->width;
|
toplevel->configure_width = toplevel->width;
|
||||||
toplevel->configure_height = toplevel->height;
|
toplevel->configure_height = toplevel->height;
|
||||||
|
|
||||||
|
@ -2248,7 +2267,12 @@ SetMode (struct wl_client *client, struct wl_resource *resource,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SendDecorationConfigure (decoration->toplevel);
|
/* According to #wayland the configure event shouldn't be sent for
|
||||||
|
partially initialized surfaces. */
|
||||||
|
if (decoration->toplevel->state & StateEverMapped)
|
||||||
|
SendDecorationConfigure (decoration->toplevel);
|
||||||
|
else
|
||||||
|
decoration->toplevel->state |= StateNeedDecorationConfigure;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2263,7 +2287,13 @@ UnsetMode (struct wl_client *client, struct wl_resource *resource)
|
||||||
|
|
||||||
/* Default to using window manager decorations. */
|
/* Default to using window manager decorations. */
|
||||||
decoration->toplevel->decor = DecorationModeWindowManager;
|
decoration->toplevel->decor = DecorationModeWindowManager;
|
||||||
SendDecorationConfigure (decoration->toplevel);
|
|
||||||
|
/* According to #wayland the configure event shouldn't be sent for
|
||||||
|
partially initialized surfaces. */
|
||||||
|
if (decoration->toplevel->state & StateEverMapped)
|
||||||
|
SendDecorationConfigure (decoration->toplevel);
|
||||||
|
else
|
||||||
|
decoration->toplevel->state |= StateNeedDecorationConfigure;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct zxdg_toplevel_decoration_v1_interface decoration_impl =
|
static struct zxdg_toplevel_decoration_v1_interface decoration_impl =
|
||||||
|
|
Loading…
Add table
Reference in a new issue