Skip to content

Commit

Permalink
monitor: Attempt to fix lock-bypassing
Browse files Browse the repository at this point in the history
This is a by-hand application of
mate-desktop/mate-screensaver#167. It cannot be
done automatically because the two codebases are quite diverged at this
point.

The idea is that instead of listening to the `monitor-changed` on
GdkScreen, we listen for the `monitor-added` and `monitor-removed`
signals on GdkDisplay, making dynamic monitor changes more reliable.

Signed-off-by: Evan Maddock <[email protected]>
  • Loading branch information
EbonJaeger committed Apr 17, 2024
1 parent a19afe5 commit 01e6e1a
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 174 deletions.
199 changes: 108 additions & 91 deletions src/gs-manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,6 @@ static GSWindow *
find_window_at_pointer (GSManager *manager)
{
GdkDisplay *display;
GdkScreen *screen;
GdkMonitor *monitor;
int x, y;
GSWindow *window;
Expand All @@ -648,25 +647,27 @@ find_window_at_pointer (GSManager *manager)
display = gdk_display_get_default ();
GdkSeat* seat = gdk_display_get_default_seat (display);
GdkDevice* pointer = gdk_seat_get_pointer (seat);
gdk_device_get_position (pointer, &screen, &x, &y);
gdk_device_get_position (pointer, NULL, &x, &y);
monitor = gdk_display_get_monitor_at_point (display, x, y);

/* Find the gs-window that is on that screen */
/* Find the gs-window that is on that monitor */
window = NULL;
for (l = manager->priv->windows; l; l = l->next) {
GSWindow *win = GS_WINDOW (l->data);
if (gs_window_get_screen (win) == screen
&& gdk_display_get_monitor (display, gs_window_get_monitor (win)) == monitor) {
if (gs_window_get_display (win) == display
&& gs_window_get_monitor (win) == monitor) {
window = win;
}
}

if (window == NULL) {
gs_debug ("WARNING: Could not find the GSWindow for screen 0");
gs_debug ("WARNING: Could not find the GSWindow for display &s",
gdk_display_get_name (display));
/* take the first one */
window = manager->priv->windows->data;
} else {
gs_debug ("Requesting unlock for screen 0");
gs_debug ("Requesting unlock for display %s",
gdk_display_get_name (display));
}

return window;
Expand Down Expand Up @@ -694,21 +695,20 @@ manager_maybe_grab_window (GSManager *manager,
GSWindow *window)
{
GdkDisplay *display;
GdkScreen *screen;
GdkMonitor *monitor;
int x, y;
gboolean grabbed;

display = gdk_display_get_default ();
GdkSeat* seat = gdk_display_get_default_seat (display);
GdkDevice* pointer = gdk_seat_get_pointer (seat);
gdk_device_get_position (pointer, &screen, &x, &y);
gdk_device_get_position (pointer, NULL, &x, &y);
monitor = gdk_display_get_monitor_at_point (display, x, y);

gdk_display_flush (display);
grabbed = FALSE;
if (gs_window_get_screen (window) == screen
&& gdk_display_get_monitor (display, gs_window_get_monitor (window)) == monitor) {
if (gs_window_get_display (window) == display
&& gs_window_get_monitor (window) == monitor) {
gs_debug ("Moving grab to %p", window);
gs_grab_move_to_window (manager->priv->grab,
gs_window_get_gdk_window (window),
Expand Down Expand Up @@ -799,7 +799,7 @@ apply_background_to_window (GSManager *manager,
}

gdk_window = gs_window_get_gdk_window (window);
monitor = gdk_display_get_monitor_at_window (gdk_display_get_default (), gdk_window);
monitor = gs_window_get_monitor (window);
gdk_monitor_get_geometry (monitor, &monitor_geometry);
width = monitor_geometry.width;
height = monitor_geometry.height;
Expand Down Expand Up @@ -977,19 +977,17 @@ connect_window_signals (GSManager *manager,

static void
gs_manager_create_window_for_monitor (GSManager *manager,
GdkScreen *screen,
int monitor_index)
GdkMonitor *monitor)
{
GSWindow *window;
GdkRectangle rect;

GdkMonitor* monitor = gdk_display_get_monitor(gdk_display_get_default(), monitor_index);
gdk_monitor_get_geometry (monitor, &rect);

gs_debug ("Creating window for monitor %d [%d,%d] (%dx%d)",
monitor_index, rect.x, rect.y, rect.width, rect.height);
gs_debug ("Creating a window [%d,%d] (%dx%d)",
rect.x, rect.y, rect.width, rect.height);

window = gs_window_new (screen, monitor_index, manager->priv->lock_active);
window = gs_window_new (monitor, manager->priv->lock_active);

gs_window_set_user_switch_enabled (window, manager->priv->user_switch_enabled);
gs_window_set_logout_enabled (window, manager->priv->logout_enabled);
Expand All @@ -1009,68 +1007,80 @@ gs_manager_create_window_for_monitor (GSManager *manager,
}

static void
on_screen_monitors_changed (GdkScreen *screen,
GSManager *manager)
on_display_monitor_added (GdkDisplay *display,
GdkMonitor *monitor,
GSManager *manager)
{
GSList *l;
int n_monitors;
int n_windows;
int i;
GSList *l;
int n_monitors;

n_monitors = gdk_display_get_n_monitors (gdk_display_get_default ());
n_windows = g_slist_length (manager->priv->windows);
n_monitors = gdk_display_get_n_monitors (display);

gs_debug ("Monitors changed for screen 0: num=%d", n_monitors);
gs_debug ("Monitor added on display %s, now there are %d",
gdk_display_get_name (display), n_monitors);

if (n_monitors > n_windows) {
/* Tear down the unlock dialog in case we want to move it
* to the new monitor
*/
l = manager->priv->windows;
while (l != NULL)
{
gs_window_cancel_unlock_request (GS_WINDOW (l->data));
l = l->next;
}

/* Tear down unlock dialog in case we want to move it
* to a new monitor
*/
l = manager->priv->windows;
while (l != NULL) {
gs_window_cancel_unlock_request (GS_WINDOW (l->data));
l = l->next;
}
/* add a new window */
gs_manager_create_window_for_monitor (manager, monitor);

/* add more windows */
for (i = n_windows; i < n_monitors; i++) {
gs_manager_create_window_for_monitor (manager, screen, i);
}

/* And put unlock dialog up where ever it's supposed to be
*/
gs_manager_request_unlock (manager);
} else {

gdk_x11_grab_server ();

/* remove the extra windows */
l = manager->priv->windows;
while (l != NULL) {
GdkScreen *this_screen;
int this_monitor;
GSList *next = l->next;

this_screen = gs_window_get_screen (GS_WINDOW (l->data));
this_monitor = gs_window_get_monitor (GS_WINDOW (l->data));
if (this_screen == screen && this_monitor >= n_monitors) {
gs_window_destroy (GS_WINDOW (l->data));
manager->priv->windows = g_slist_delete_link (manager->priv->windows, l);
}
l = next;
}
/* and put unlock dialog up whereever it's supposed to be */
gs_manager_request_unlock (manager);
}

/* make sure there is a lock dialog on a connected monitor,
static void
on_display_monitor_removed (GdkDisplay *display,
GdkMonitor *monitor,
GSManager *manager)
{
GSList *l;
int n_monitors;
int n_windows;

n_monitors = gdk_display_get_n_monitors (display);
n_windows = g_slist_length (manager->priv->windows);

gs_debug ("Monitor removed on display %s, now there are %d",
gdk_display_get_name (display), n_monitors);

gdk_x11_grab_server ();

/* remove the now extra window */
l = manager->priv->windows;
while (l != NULL)
{
GdkDisplay *this_display;
GdkMonitor *this_monitor;
GSList *next = l->next;

this_display = gs_window_get_display (GS_WINDOW (l->data));
this_monitor = gs_window_get_monitor (GS_WINDOW (l->data));

if (this_display == display && this_monitor == monitor)
{
gs_window_destroy (GS_WINDOW (l->data));
manager->priv->windows = g_slist_delete_link (manager->priv->windows, l);
}
l = next;
}

/* make sure there is a lock dialog on a connected monitor,
* and that the keyboard is still properly grabbed after all
* the windows above got destroyed*/
if (n_windows > n_monitors) {
gs_manager_request_unlock (manager);
}
if (n_windows > n_monitors) {
gs_manager_request_unlock (manager);
}

gdk_display_flush (gdk_display_get_default ());
gdk_x11_ungrab_server ();
}
gdk_display_flush (display);
gdk_x11_ungrab_server ();
}

static void
Expand All @@ -1088,11 +1098,15 @@ gs_manager_destroy_windows (GSManager *manager)

display = gdk_display_get_default ();

g_signal_handlers_disconnect_by_func (gdk_display_get_default_screen (display),
on_screen_monitors_changed,
manager);
g_signal_handlers_disconnect_by_func (display,
on_display_monitor_removed,
manager);
g_signal_handlers_disconnect_by_func (display,
on_display_monitor_added,
manager);

for (l = manager->priv->windows; l; l = l->next) {

for (l = manager->priv->windows; l; l = l->next) {
gs_window_destroy (l->data);
}
g_slist_free (manager->priv->windows);
Expand Down Expand Up @@ -1136,51 +1150,54 @@ gs_manager_finalize (GObject *object)
}

static void
gs_manager_create_windows_for_screen (GSManager *manager,
GdkScreen *screen)
gs_manager_create_windows_for_display (GSManager *manager,
GdkDisplay *display)
{
int n_monitors;
int i;
int n_monitors;
int i;

g_return_if_fail (manager != NULL);
g_return_if_fail (GS_IS_MANAGER (manager));
g_return_if_fail (GDK_IS_SCREEN (screen));
g_return_if_fail (GDK_IS_DISPLAY (display));

g_object_ref (manager);
g_object_ref (screen);
g_object_ref (display);

n_monitors = gdk_display_get_n_monitors (gdk_display_get_default ());
n_monitors = gdk_display_get_n_monitors (display);

gs_debug ("Creating %d windows for screen 0", n_monitors);
gs_debug ("Creating %d windows for display %s", n_monitors, gdk_display_get_name (display));

for (i = 0; i < n_monitors; i++) {
gs_manager_create_window_for_monitor (manager, screen, i);
GdkMonitor *mon = gdk_display_get_monitor (display, i);
gs_manager_create_window_for_monitor (manager, mon);
}

g_object_unref (screen);
g_object_unref (display);
g_object_unref (manager);
}

static void
gs_manager_create_windows (GSManager *manager)
{
GdkDisplay *display;
GdkScreen *screen;

g_return_if_fail (manager != NULL);
g_return_if_fail (GS_IS_MANAGER (manager));

g_assert (manager->priv->windows == NULL);

display = gdk_display_get_default ();
screen = gdk_display_get_default_screen (display);

g_signal_connect (screen,
"monitors-changed",
G_CALLBACK (on_screen_monitors_changed),
manager);
g_signal_connect (display,
"monitor-added",
G_CALLBACK (on_display_monitor_added),
manager);
g_signal_connect (display,
"monitor-removed",
G_CALLBACK (on_display_monitor_removed),
manager);

gs_manager_create_windows_for_screen (manager, screen);
gs_manager_create_windows_for_display (manager, display);
}

GSManager *
Expand Down
Loading

0 comments on commit 01e6e1a

Please sign in to comment.