Automatically open new Xed window on current workspace... (#319)

...if it wasn't already opened. Otherwise, open new tab
in Xed window on current Workspace.

Fix regression #318
This commit is contained in:
Alexander Drozdov 2019-07-10 19:24:52 +10:00 committed by Clement Lefebvre
parent cd94beb376
commit f4c882e3b5
4 changed files with 274 additions and 1 deletions

View File

@ -472,6 +472,8 @@ xed_warning
xed_utils_make_valid_utf8
xed_utils_uri_get_dirname
xed_utils_replace_home_dir_with_tilde
xed_utils_get_current_workspace
xed_utils_get_window_workspace
xed_utils_activate_url
xed_utils_is_valid_uri
xed_utils_get_glade_widgets

View File

@ -356,6 +356,89 @@ xed_app_startup (GApplication *application)
app);
}
static gboolean
is_in_viewport (GtkWindow *window,
GdkScreen *screen,
gint workspace,
gint viewport_x,
gint viewport_y)
{
GdkScreen *s;
GdkDisplay *display;
GdkMonitor *monitor;
GdkWindow *gdkwindow;
GdkRectangle geometry;
const gchar *cur_name;
const gchar *name;
gint ws;
gint x, y, width, height;
/* Check for screen and display match */
display = gdk_screen_get_display (screen);
cur_name = gdk_display_get_name (display);
s = gtk_window_get_screen (window);
display = gdk_screen_get_display (s);
name = gdk_display_get_name (display);
if (strcmp (cur_name, name) != 0)
{
return FALSE;
}
/* Check for workspace match */
ws = xed_utils_get_window_workspace (window);
if (ws != workspace && ws != XED_ALL_WORKSPACES)
{
return FALSE;
}
/* Check for viewport match */
gdkwindow = gtk_widget_get_window (GTK_WIDGET (window));
gdk_window_get_position (gdkwindow, &x, &y);
width = gdk_window_get_width (gdkwindow);
height = gdk_window_get_height (gdkwindow);
x += viewport_x;
y += viewport_y;
monitor = gdk_display_get_monitor_at_window(display, gdkwindow);
gdk_monitor_get_geometry(monitor, &geometry);
return x + width * .75 >= geometry.x &&
x + width * .25 <= geometry.x + geometry.width &&
y + height * .75 >= geometry.y &&
y + height * .25 <= geometry.y + geometry.height;
}
static XedWindow *
get_active_window (GtkApplication *app)
{
GdkScreen *screen;
guint workspace;
gint viewport_x, viewport_y;
GList *windows, *l;
screen = gdk_screen_get_default ();
workspace = xed_utils_get_current_workspace (screen);
xed_utils_get_current_viewport (screen, &viewport_x, &viewport_y);
/* Gtk documentation says the window list is always in MRU order */
windows = gtk_application_get_windows (app);
for (l = windows; l != NULL; l = l->next)
{
GtkWindow *window = l->data;
if (XED_IS_WINDOW (window) && is_in_viewport (window, screen, workspace, viewport_x, viewport_y))
{
return XED_WINDOW (window);
}
}
return NULL;
}
static void
set_command_line_wait (XedApp *app,
XedTab *tab)
@ -392,7 +475,7 @@ open_files (GApplication *application,
if (!new_window)
{
window = XED_WINDOW (gtk_application_get_active_window (GTK_APPLICATION (application)));
window = get_active_window (GTK_APPLICATION (application));
}
if (window == NULL)

View File

@ -414,6 +414,186 @@ xed_utils_uri_get_dirname (const gchar *uri)
return res;
}
/* the following two functions are courtesy of galeon */
/**
* xed_utils_get_current_workspace:
* @screen: a #GdkScreen
*
* Get the currently visible workspace for the #GdkScreen.
*
* If the X11 window property isn't found, 0 (the first workspace)
* is returned.
*/
guint
xed_utils_get_current_workspace (GdkScreen *screen)
{
#ifdef GDK_WINDOWING_X11
GdkWindow *root_win;
GdkDisplay *display;
guint ret = 0;
g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
root_win = gdk_screen_get_root_window (screen);
display = gdk_screen_get_display (screen);
if (GDK_IS_X11_DISPLAY (display))
{
Atom type;
gint format;
gulong nitems;
gulong bytes_after;
guint *current_desktop;
gint err, result;
gdk_x11_display_error_trap_push (display);
result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (root_win),
gdk_x11_get_xatom_by_name_for_display (display, "_NET_CURRENT_DESKTOP"),
0, G_MAXLONG, False, XA_CARDINAL, &type, &format, &nitems,
&bytes_after, (gpointer) &current_desktop);
err = gdk_x11_display_error_trap_pop (display);
if (err != Success || result != Success)
return ret;
if (type == XA_CARDINAL && format == 32 && nitems > 0)
ret = current_desktop[0];
XFree (current_desktop);
}
return ret;
#else
/* FIXME: on mac etc proably there are native APIs
* to get the current workspace etc */
return 0;
#endif
}
/**
* xed_utils_get_window_workspace:
* @gtkwindow: a #GtkWindow.
*
* Get the workspace the window is on.
*
* This function gets the workspace that the #GtkWindow is visible on,
* it returns XED_ALL_WORKSPACES if the window is sticky, or if
* the window manager doesn't support this function.
*
* Returns: the workspace the window is on.
*/
guint
xed_utils_get_window_workspace (GtkWindow *gtkwindow)
{
#ifdef GDK_WINDOWING_X11
GdkWindow *window;
GdkDisplay *display;
Atom type;
gint format;
gulong nitems;
gulong bytes_after;
guint *workspace;
gint err, result;
guint ret = XED_ALL_WORKSPACES;
g_return_val_if_fail (GTK_IS_WINDOW (gtkwindow), 0);
g_return_val_if_fail (gtk_widget_get_realized (GTK_WIDGET (gtkwindow)), 0);
window = gtk_widget_get_window (GTK_WIDGET (gtkwindow));
display = gdk_window_get_display (window);
if (GDK_IS_X11_DISPLAY (display))
{
gdk_x11_display_error_trap_push (display);
result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
0, G_MAXLONG, False, XA_CARDINAL, &type, &format, &nitems,
&bytes_after, (gpointer) &workspace);
err = gdk_x11_display_error_trap_pop (display);
if (err != Success || result != Success)
return ret;
if (type == XA_CARDINAL && format == 32 && nitems > 0)
ret = workspace[0];
XFree (workspace);
}
return ret;
#else
/* FIXME: on mac etc proably there are native APIs
* to get the current workspace etc */
return 0;
#endif
}
/**
* xed_utils_get_current_viewport:
* @screen: a #GdkScreen
* @x: (out): x-axis point.
* @y: (out): y-axis point.
*
* Get the currently visible viewport origin for the #GdkScreen.
*
* If the X11 window property isn't found, (0, 0) is returned.
*/
void
xed_utils_get_current_viewport (GdkScreen *screen,
gint *x,
gint *y)
{
#ifdef GDK_WINDOWING_X11
GdkWindow *root_win;
GdkDisplay *display;
Atom type;
gint format;
gulong nitems;
gulong bytes_after;
gulong *coordinates;
gint err, result;
g_return_if_fail (GDK_IS_SCREEN (screen));
g_return_if_fail (x != NULL && y != NULL);
/* Default values for the viewport origin */
*x = 0;
*y = 0;
root_win = gdk_screen_get_root_window (screen);
display = gdk_screen_get_display (screen);
if (GDK_IS_X11_DISPLAY (display))
{
gdk_x11_display_error_trap_push (display);
result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (root_win),
gdk_x11_get_xatom_by_name_for_display (display, "_NET_DESKTOP_VIEWPORT"),
0, G_MAXLONG, False, XA_CARDINAL, &type, &format, &nitems,
&bytes_after, (void*) &coordinates);
err = gdk_x11_display_error_trap_pop (display);
if (err != Success || result != Success)
return;
if (type != XA_CARDINAL || format != 32 || nitems < 2)
{
XFree (coordinates);
return;
}
*x = coordinates[0];
*y = coordinates[1];
XFree (coordinates);
}
#else
/* FIXME: on mac etc proably there are native APIs
* to get the current workspace etc */
*x = 0;
*y = 0;
#endif
}
/**
* xed_utils_location_get_dirname_for_display
* @file: the location

View File

@ -85,6 +85,14 @@ gchar *xed_utils_location_get_dirname_for_display (GFile *location);
gchar *xed_utils_replace_home_dir_with_tilde (const gchar *uri);
guint xed_utils_get_current_workspace (GdkScreen *screen);
guint xed_utils_get_window_workspace (GtkWindow *gtkwindow);
void xed_utils_get_current_viewport (GdkScreen *screen,
gint *x,
gint *y);
gboolean xed_utils_is_valid_location (GFile *location);
gboolean xed_utils_get_ui_objects (const gchar *filename,