forked from 12to11/12to11
Improve behavior under older window managers
* 12to11.man: Update documentation. * compositor.h (enum _FocusMode): New enum. (struct _RoleFuncs, struct _XdgRoleImplementationFuncs): Add `note_focus'. * seat.c (CancelResizeOperation, InterceptButtonEventForResize): Re-enter surface underneath pointer upon completion. (InterceptResizeEvent): Accept subcompositor argument. (NoticeDeviceDisabled): Unfocus surface upon the seat becoming inert. (SetFocusSurface): Call surface note_focus function. (DispatchMotion, DispatchButton): Adjust calls to InterceptResizeEvent. (HandleResizeUnmapped): Adjust calls to CancelResizeOperation. (DispatchBarrierHit): Use correct surface. (FakePointerEdge): Leave any entered surface, as button events will no longer be reported. * surface.c (XLSurfaceNoteFocus): New function. * xdg_surface.c (NoteFocus): New function. (XLGetXdgSurface): Attach new function. * xdg_toplevel.c (struct _XdgToplevel): New field focus_seat_count. (SendStates): Don't compute width and height when just sending state. (NoteFocus): Increment focus seat count. (XLGetXdgToplevel): Attach new function if the window manager does not support _NET_WM_STATE_FOCUSED.
This commit is contained in:
parent
d38093f59e
commit
b515414946
6 changed files with 161 additions and 42 deletions
|
@ -245,10 +245,7 @@ environment variable may help.
|
||||||
Using this protocol translator under a window manager that does not at
|
Using this protocol translator under a window manager that does not at
|
||||||
least support the
|
least support the
|
||||||
.B _NET_WM_SYNC_REQUEST
|
.B _NET_WM_SYNC_REQUEST
|
||||||
and
|
window manager protocol will result in Wayland programs running badly.
|
||||||
.B _NET_WM_STATE
|
|
||||||
window manager hints will result in Wayland programs running
|
|
||||||
incorrectly.
|
|
||||||
.PP
|
.PP
|
||||||
In addition, surfaces transforms are not supported nor reported. The
|
In addition, surfaces transforms are not supported nor reported. The
|
||||||
vast majority of clients seem not to make use of this feature, and
|
vast majority of clients seem not to make use of this feature, and
|
||||||
|
|
10
compositor.h
10
compositor.h
|
@ -816,6 +816,13 @@ typedef struct _SyncRelease SyncRelease;
|
||||||
typedef struct _State State;
|
typedef struct _State State;
|
||||||
typedef struct _FrameCallback FrameCallback;
|
typedef struct _FrameCallback FrameCallback;
|
||||||
typedef enum _RoleType RoleType;
|
typedef enum _RoleType RoleType;
|
||||||
|
typedef enum _FocusMode FocusMode;
|
||||||
|
|
||||||
|
enum _FocusMode
|
||||||
|
{
|
||||||
|
SurfaceFocusIn,
|
||||||
|
SurfaceFocusOut,
|
||||||
|
};
|
||||||
|
|
||||||
enum _RoleType
|
enum _RoleType
|
||||||
{
|
{
|
||||||
|
@ -1067,6 +1074,7 @@ struct _RoleFuncs
|
||||||
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);
|
void (*select_extra_events) (Surface *, Role *, unsigned long);
|
||||||
|
void (*note_focus) (Surface *, Role *, FocusMode);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Role
|
struct _Role
|
||||||
|
@ -1116,6 +1124,7 @@ 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 XLSurfaceSelectExtraEvents (Surface *, unsigned long);
|
||||||
|
extern void XLSurfaceNoteFocus (Surface *, FocusMode);
|
||||||
|
|
||||||
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 *);
|
||||||
|
@ -1257,6 +1266,7 @@ struct _XdgRoleImplementationFuncs
|
||||||
void (*post_resize) (Role *, XdgRoleImplementation *, int, int, int, int);
|
void (*post_resize) (Role *, XdgRoleImplementation *, int, int, int, int);
|
||||||
void (*commit_inside_frame) (Role *, XdgRoleImplementation *);
|
void (*commit_inside_frame) (Role *, XdgRoleImplementation *);
|
||||||
Bool (*is_window_mapped) (Role *, XdgRoleImplementation *);
|
Bool (*is_window_mapped) (Role *, XdgRoleImplementation *);
|
||||||
|
void (*note_focus) (Role *, XdgRoleImplementation *, FocusMode);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _XdgRoleImplementation
|
struct _XdgRoleImplementation
|
||||||
|
|
87
seat.c
87
seat.c
|
@ -1996,9 +1996,18 @@ RunResizeDoneCallbacks (Seat *seat)
|
||||||
seat->resize_callbacks.last = &seat->resize_callbacks;
|
seat->resize_callbacks.last = &seat->resize_callbacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Forward declarations. */
|
||||||
|
static void TransformToSurface (Surface *, double, double, double *, double *);
|
||||||
|
static Surface *FindSurfaceUnder (Subcompositor *, double, double);
|
||||||
|
static void EnteredSurface (Seat *, Surface *, Time, double, double, Bool);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
CancelResizeOperation (Seat *seat, Time time)
|
CancelResizeOperation (Seat *seat, Time time, Subcompositor *subcompositor,
|
||||||
|
XIDeviceEvent *xev)
|
||||||
{
|
{
|
||||||
|
Surface *dispatch;
|
||||||
|
double x, y;
|
||||||
|
|
||||||
/* Stop the resize operation. */
|
/* Stop the resize operation. */
|
||||||
XLSurfaceCancelUnmapCallback (seat->resize_surface_callback);
|
XLSurfaceCancelUnmapCallback (seat->resize_surface_callback);
|
||||||
seat->resize_surface = NULL;
|
seat->resize_surface = NULL;
|
||||||
|
@ -2008,11 +2017,30 @@ CancelResizeOperation (Seat *seat, Time time)
|
||||||
|
|
||||||
/* Ungrab the pointer. */
|
/* Ungrab the pointer. */
|
||||||
XIUngrabDevice (compositor.display, seat->master_pointer,
|
XIUngrabDevice (compositor.display, seat->master_pointer,
|
||||||
time);
|
xev->time);
|
||||||
|
|
||||||
|
if (!subcompositor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* If there's no focus surface, look up the surface and enter
|
||||||
|
it. The grab should not be held at this point. */
|
||||||
|
dispatch = FindSurfaceUnder (subcompositor, xev->event_x, xev->event_y);
|
||||||
|
|
||||||
|
if (dispatch)
|
||||||
|
{
|
||||||
|
TransformToSurface (dispatch, xev->event_x, xev->event_y, &x, &y);
|
||||||
|
|
||||||
|
/* Enter the surface. */
|
||||||
|
EnteredSurface (seat, dispatch, xev->time, x, y, False);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, there should be no need to leave any entered surface,
|
||||||
|
since the entered surface should be NULL already. */
|
||||||
}
|
}
|
||||||
|
|
||||||
static Bool
|
static Bool
|
||||||
InterceptButtonEventForResize (Seat *seat, XIDeviceEvent *xev)
|
InterceptButtonEventForResize (Seat *seat, Subcompositor *subcompositor,
|
||||||
|
XIDeviceEvent *xev)
|
||||||
{
|
{
|
||||||
if (xev->type == XI_ButtonPress)
|
if (xev->type == XI_ButtonPress)
|
||||||
return True;
|
return True;
|
||||||
|
@ -2020,7 +2048,7 @@ InterceptButtonEventForResize (Seat *seat, XIDeviceEvent *xev)
|
||||||
/* If the button starting the resize has been released, cancel the
|
/* If the button starting the resize has been released, cancel the
|
||||||
resize operation. */
|
resize operation. */
|
||||||
if (xev->detail == seat->resize_button)
|
if (xev->detail == seat->resize_button)
|
||||||
CancelResizeOperation (seat, xev->time);
|
CancelResizeOperation (seat, xev->time, subcompositor, xev);
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
@ -2114,7 +2142,8 @@ InterceptMotionEventForResize (Seat *seat, XIDeviceEvent *xev)
|
||||||
}
|
}
|
||||||
|
|
||||||
static Bool
|
static Bool
|
||||||
InterceptResizeEvent (Seat *seat, XIDeviceEvent *xev)
|
InterceptResizeEvent (Seat *seat, Subcompositor *subcompositor,
|
||||||
|
XIDeviceEvent *xev)
|
||||||
{
|
{
|
||||||
if (!seat->resize_surface)
|
if (!seat->resize_surface)
|
||||||
return False;
|
return False;
|
||||||
|
@ -2122,7 +2151,7 @@ InterceptResizeEvent (Seat *seat, XIDeviceEvent *xev)
|
||||||
switch (xev->evtype)
|
switch (xev->evtype)
|
||||||
{
|
{
|
||||||
case XI_ButtonRelease:
|
case XI_ButtonRelease:
|
||||||
return InterceptButtonEventForResize (seat, xev);
|
return InterceptButtonEventForResize (seat, subcompositor, xev);
|
||||||
|
|
||||||
case XI_Motion:
|
case XI_Motion:
|
||||||
return InterceptMotionEventForResize (seat, xev);
|
return InterceptMotionEventForResize (seat, xev);
|
||||||
|
@ -2145,6 +2174,9 @@ RunDestroyListeners (Seat *seat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Forward declaration. */
|
||||||
|
static void SetFocusSurface (Seat *, Surface *);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
NoticeDeviceDisabled (int deviceid)
|
NoticeDeviceDisabled (int deviceid)
|
||||||
{
|
{
|
||||||
|
@ -2174,6 +2206,11 @@ NoticeDeviceDisabled (int deviceid)
|
||||||
|
|
||||||
seat->flags |= IsInert;
|
seat->flags |= IsInert;
|
||||||
|
|
||||||
|
/* Set the focus surface to NULL, so surfaces don't mistakenly
|
||||||
|
treat themselves as still focused. */
|
||||||
|
|
||||||
|
SetFocusSurface (seat, NULL);
|
||||||
|
|
||||||
/* Run destroy handlers. */
|
/* Run destroy handlers. */
|
||||||
|
|
||||||
RunDestroyListeners (seat);
|
RunDestroyListeners (seat);
|
||||||
|
@ -2455,7 +2492,6 @@ HandleResizeComplete (Seat *seat)
|
||||||
/* Forward declarations. */
|
/* Forward declarations. */
|
||||||
|
|
||||||
static int GetXButton (int);
|
static int GetXButton (int);
|
||||||
static void TransformToSurface (Surface *, double, double, double *, double *);
|
|
||||||
static void SendButton (Seat *, Surface *, Time, uint32_t, uint32_t,
|
static void SendButton (Seat *, Surface *, Time, uint32_t, uint32_t,
|
||||||
double, double);
|
double, double);
|
||||||
|
|
||||||
|
@ -2871,6 +2907,9 @@ SetFocusSurface (Seat *seat, Surface *focus)
|
||||||
{
|
{
|
||||||
SendKeyboardLeave (seat, seat->focus_surface);
|
SendKeyboardLeave (seat, seat->focus_surface);
|
||||||
|
|
||||||
|
/* Tell the surface it's no longer focused. */
|
||||||
|
XLSurfaceNoteFocus (seat->focus_surface, SurfaceFocusOut);
|
||||||
|
|
||||||
/* Cancel any grab that may be associated with shortcut
|
/* Cancel any grab that may be associated with shortcut
|
||||||
inhibition. */
|
inhibition. */
|
||||||
XLReleaseShortcutInhibition (seat, seat->focus_surface);
|
XLReleaseShortcutInhibition (seat, seat->focus_surface);
|
||||||
|
@ -2905,6 +2944,9 @@ SetFocusSurface (Seat *seat, Surface *focus)
|
||||||
|
|
||||||
SendKeyboardEnter (seat, focus);
|
SendKeyboardEnter (seat, focus);
|
||||||
|
|
||||||
|
/* Tell the surface it's now focused. */
|
||||||
|
XLSurfaceNoteFocus (seat->focus_surface, SurfaceFocusIn);
|
||||||
|
|
||||||
XLPrimarySelectionHandleFocusChange (seat);
|
XLPrimarySelectionHandleFocusChange (seat);
|
||||||
|
|
||||||
if (seat->data_device)
|
if (seat->data_device)
|
||||||
|
@ -3807,7 +3849,7 @@ DispatchMotion (Subcompositor *subcompositor, XIDeviceEvent *xev)
|
||||||
if (!seat)
|
if (!seat)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (InterceptResizeEvent (seat, xev))
|
if (InterceptResizeEvent (seat, subcompositor, xev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Move the drag-and-drop icon window. */
|
/* Move the drag-and-drop icon window. */
|
||||||
|
@ -3834,8 +3876,7 @@ DispatchMotion (Subcompositor *subcompositor, XIDeviceEvent *xev)
|
||||||
dispatch = seat->last_seen_surface;
|
dispatch = seat->last_seen_surface;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dispatch = FindSurfaceUnder (subcompositor, xev->event_x,
|
dispatch = actual_dispatch;
|
||||||
xev->event_y);
|
|
||||||
|
|
||||||
event_x = xev->event_x;
|
event_x = xev->event_x;
|
||||||
event_y = xev->event_y;
|
event_y = xev->event_y;
|
||||||
|
@ -4080,7 +4121,7 @@ DispatchButton (Subcompositor *subcompositor, XIDeviceEvent *xev)
|
||||||
if (!seat)
|
if (!seat)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (InterceptResizeEvent (seat, xev))
|
if (InterceptResizeEvent (seat, subcompositor, xev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (seat->flags & IsDragging)
|
if (seat->flags & IsDragging)
|
||||||
|
@ -4265,8 +4306,8 @@ DispatchBarrierHit (XIBarrierEvent *barrier)
|
||||||
|
|
||||||
/* Report a barrier hit event as relative motion. */
|
/* Report a barrier hit event as relative motion. */
|
||||||
|
|
||||||
if (seat->focus_surface)
|
if (seat->last_seen_surface)
|
||||||
SendRelativeMotion (seat, seat->focus_surface,
|
SendRelativeMotion (seat, seat->last_seen_surface,
|
||||||
barrier->dx, barrier->dy,
|
barrier->dx, barrier->dy,
|
||||||
barrier->time);
|
barrier->time);
|
||||||
|
|
||||||
|
@ -4538,9 +4579,14 @@ HandleKeyboardEdge (Seat *seat, Surface *target, uint32_t serial,
|
||||||
seat->its_press_time);
|
seat->its_press_time);
|
||||||
|
|
||||||
/* Clear the grab immediately since it is no longer used. */
|
/* Clear the grab immediately since it is no longer used. */
|
||||||
|
|
||||||
if (seat->grab_held)
|
if (seat->grab_held)
|
||||||
CancelGrabEarly (seat);
|
CancelGrabEarly (seat);
|
||||||
|
|
||||||
|
/* Send leave to any surface that the pointer is currently within.
|
||||||
|
The position of the pointer is then restored upon entry. */
|
||||||
|
EnteredSurface (seat, NULL, seat->its_press_time, 0, 0, False);
|
||||||
|
|
||||||
/* Send the message to the window manager. */
|
/* Send the message to the window manager. */
|
||||||
XSendEvent (compositor.display,
|
XSendEvent (compositor.display,
|
||||||
DefaultRootWindow (compositor.display),
|
DefaultRootWindow (compositor.display),
|
||||||
|
@ -4559,7 +4605,8 @@ HandleResizeUnmapped (void *data)
|
||||||
Seat *seat;
|
Seat *seat;
|
||||||
|
|
||||||
seat = data;
|
seat = data;
|
||||||
CancelResizeOperation (seat, seat->resize_time);
|
CancelResizeOperation (seat, seat->resize_time,
|
||||||
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Bool
|
static Bool
|
||||||
|
@ -4626,13 +4673,15 @@ FakePointerEdge (Seat *seat, Surface *target, uint32_t serial,
|
||||||
if (state != Success)
|
if (state != Success)
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
/* On the other hand, cancel focus locking, since we will not be
|
/* On the other hand, cancel focus locking and leave the surface,
|
||||||
reporting motion events until the resize operation completes.
|
since we will not be reporting motion events until the resize
|
||||||
|
operation completes. */
|
||||||
|
|
||||||
Send leave events to any surface, since the pointer is
|
|
||||||
(logically) no longer inside. */
|
|
||||||
if (seat->grab_held)
|
if (seat->grab_held)
|
||||||
CancelGrabEarly (seat);
|
{
|
||||||
|
SwapUnlockSurface (seat, NULL);
|
||||||
|
CancelGrabEarly (seat);
|
||||||
|
}
|
||||||
|
|
||||||
/* Set the surface as the surface undergoing resize. */
|
/* Set the surface as the surface undergoing resize. */
|
||||||
seat->resize_surface = target;
|
seat->resize_surface = target;
|
||||||
|
|
15
surface.c
15
surface.c
|
@ -1741,6 +1741,21 @@ XLSurfaceSelectExtraEvents (Surface *surface, unsigned long event_mask)
|
||||||
event_mask);
|
event_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This function doesn't provide the seat that has now been focused
|
||||||
|
in. It is assumed that the role will perform some kind of
|
||||||
|
reference counting in order to determine how many seats currently
|
||||||
|
have it focused. */
|
||||||
|
|
||||||
|
void
|
||||||
|
XLSurfaceNoteFocus (Surface *surface, FocusMode focus)
|
||||||
|
{
|
||||||
|
if (!surface->role || !surface->role->funcs.note_focus)
|
||||||
|
return;
|
||||||
|
|
||||||
|
surface->role->funcs.note_focus (surface, surface->role,
|
||||||
|
focus);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* The following functions convert from window to surface
|
/* The following functions convert from window to surface
|
||||||
|
|
|
@ -1424,6 +1424,18 @@ SelectExtraEvents (Surface *surface, Role *role,
|
||||||
DefaultEventMask | event_mask);
|
DefaultEventMask | event_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
NoteFocus (Surface *surface, Role *role, FocusMode focus)
|
||||||
|
{
|
||||||
|
XdgRole *xdg_role;
|
||||||
|
|
||||||
|
xdg_role = XdgRoleFromRole (role);
|
||||||
|
|
||||||
|
if (xdg_role->impl && xdg_role->impl->funcs.note_focus)
|
||||||
|
xdg_role->impl->funcs.note_focus (role, xdg_role->impl,
|
||||||
|
focus);
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
@ -1509,6 +1521,7 @@ XLGetXdgSurface (struct wl_client *client, struct wl_resource *resource,
|
||||||
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;
|
role->role.funcs.select_extra_events = SelectExtraEvents;
|
||||||
|
role->role.funcs.note_focus = NoteFocus;
|
||||||
|
|
||||||
attrs.colormap = compositor.colormap;
|
attrs.colormap = compositor.colormap;
|
||||||
attrs.border_pixel = border_pixel;
|
attrs.border_pixel = border_pixel;
|
||||||
|
|
|
@ -232,6 +232,9 @@ struct _XdgToplevel
|
||||||
StatePendingConfigureSize is set. */
|
StatePendingConfigureSize is set. */
|
||||||
int configure_width, configure_height;
|
int configure_width, configure_height;
|
||||||
|
|
||||||
|
/* The number of seats that currently have this surface focused. */
|
||||||
|
int focus_seat_count;
|
||||||
|
|
||||||
/* Array of states. */
|
/* Array of states. */
|
||||||
struct wl_array states;
|
struct wl_array states;
|
||||||
|
|
||||||
|
@ -571,27 +574,14 @@ WriteStates (XdgToplevel *toplevel)
|
||||||
static void
|
static void
|
||||||
SendStates (XdgToplevel *toplevel)
|
SendStates (XdgToplevel *toplevel)
|
||||||
{
|
{
|
||||||
int width, height;
|
|
||||||
|
|
||||||
WriteStates (toplevel);
|
WriteStates (toplevel);
|
||||||
|
|
||||||
/* Adjust the width and height we're sending by the window
|
/* When SendStates is called, it means the width and height of the
|
||||||
geometry. */
|
surface did not change. weston-terminal and some other clients
|
||||||
if (toplevel->state & StateMissingState)
|
that implement resize increments themselves will keep growing
|
||||||
XLXdgRoleGetCurrentGeometry (toplevel->role, NULL, NULL,
|
their toplevels if width and height are specified here, so simply
|
||||||
&width, &height);
|
send 0, 0 to make those clients decide their own size. */
|
||||||
else
|
SendConfigure (toplevel, 0, 0);
|
||||||
{
|
|
||||||
/* toplevel->role->surface should not be NULL here. */
|
|
||||||
TruncateScaleToSurface (toplevel->role->surface,
|
|
||||||
toplevel->width, toplevel->height,
|
|
||||||
&width, &height);
|
|
||||||
|
|
||||||
XLXdgRoleCalcNewWindowSize (toplevel->role, width,
|
|
||||||
height, &width, &height);
|
|
||||||
}
|
|
||||||
|
|
||||||
SendConfigure (toplevel, width, height);
|
|
||||||
|
|
||||||
/* Mark the state has having been calculated if some state
|
/* Mark the state has having been calculated if some state
|
||||||
transition has occured. */
|
transition has occured. */
|
||||||
|
@ -2148,6 +2138,46 @@ ReplyToPing (XEvent *event)
|
||||||
| SubstructureNotifyMask), ©);
|
| SubstructureNotifyMask), ©);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
NoteFocus (Role *role, XdgRoleImplementation *impl, FocusMode mode)
|
||||||
|
{
|
||||||
|
XdgToplevel *toplevel;
|
||||||
|
int old_focus;
|
||||||
|
|
||||||
|
toplevel = ToplevelFromRoleImpl (impl);
|
||||||
|
old_focus = toplevel->focus_seat_count;
|
||||||
|
|
||||||
|
/* Increase or decrease the number of seats that currently have this
|
||||||
|
surface under input focus. */
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case SurfaceFocusIn:
|
||||||
|
toplevel->focus_seat_count++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SurfaceFocusOut:
|
||||||
|
toplevel->focus_seat_count
|
||||||
|
= MAX (toplevel->focus_seat_count - 1, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now, change the toplevel state accordingly. */
|
||||||
|
if (old_focus && !toplevel->focus_seat_count)
|
||||||
|
{
|
||||||
|
/* The surface should no longer be activated. */
|
||||||
|
toplevel->toplevel_state.activated = False;
|
||||||
|
WriteStates (toplevel);
|
||||||
|
SendStates (toplevel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The surface should now be activated. */
|
||||||
|
toplevel->toplevel_state.activated = True;
|
||||||
|
WriteStates (toplevel);
|
||||||
|
SendStates (toplevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const struct xdg_toplevel_interface xdg_toplevel_impl =
|
static const struct xdg_toplevel_interface xdg_toplevel_impl =
|
||||||
{
|
{
|
||||||
.destroy = Destroy,
|
.destroy = Destroy,
|
||||||
|
@ -2210,6 +2240,11 @@ XLGetXdgToplevel (struct wl_client *client, struct wl_resource *resource,
|
||||||
toplevel->impl.funcs.commit_inside_frame = CommitInsideFrame;
|
toplevel->impl.funcs.commit_inside_frame = CommitInsideFrame;
|
||||||
toplevel->impl.funcs.is_window_mapped = IsWindowMapped;
|
toplevel->impl.funcs.is_window_mapped = IsWindowMapped;
|
||||||
|
|
||||||
|
if (!XLWmSupportsHint (_NET_WM_STATE_FOCUSED))
|
||||||
|
/* If _NET_WM_STATE_FOCUSED is unsupported, fall back to utilizing
|
||||||
|
focus in and focus out events to determine the focus state. */
|
||||||
|
toplevel->impl.funcs.note_focus = NoteFocus;
|
||||||
|
|
||||||
/* Set up the sentinel node for the list of unmap callbacks. */
|
/* Set up the sentinel node for the list of unmap callbacks. */
|
||||||
toplevel->unmap_callbacks.next = &toplevel->unmap_callbacks;
|
toplevel->unmap_callbacks.next = &toplevel->unmap_callbacks;
|
||||||
toplevel->unmap_callbacks.last = &toplevel->unmap_callbacks;
|
toplevel->unmap_callbacks.last = &toplevel->unmap_callbacks;
|
||||||
|
|
Loading…
Add table
Reference in a new issue