Extended the popup menu to include all supported window operations
This commit is contained in:
parent
aa277cef29
commit
112b4ce7c3
|
@ -33,6 +33,17 @@ typedef enum _TasksAtom
|
||||||
TASKS_ATOM_NET_CLIENT_LIST,
|
TASKS_ATOM_NET_CLIENT_LIST,
|
||||||
TASKS_ATOM_NET_CLOSE_WINDOW,
|
TASKS_ATOM_NET_CLOSE_WINDOW,
|
||||||
TASKS_ATOM_NET_CURRENT_DESKTOP,
|
TASKS_ATOM_NET_CURRENT_DESKTOP,
|
||||||
|
TASKS_ATOM_NET_WM_ACTION_CHANGE_DESKTOP,
|
||||||
|
TASKS_ATOM_NET_WM_ACTION_CLOSE,
|
||||||
|
TASKS_ATOM_NET_WM_ACTION_MOVE,
|
||||||
|
TASKS_ATOM_NET_WM_ACTION_RESIZE,
|
||||||
|
TASKS_ATOM_NET_WM_ACTION_MINIMIZE,
|
||||||
|
TASKS_ATOM_NET_WM_ACTION_SHADE,
|
||||||
|
TASKS_ATOM_NET_WM_ACTION_STICK,
|
||||||
|
TASKS_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ,
|
||||||
|
TASKS_ATOM_NET_WM_ACTION_MAXIMIZE_VERT,
|
||||||
|
TASKS_ATOM_NET_WM_ACTION_FULLSCREEN,
|
||||||
|
TASKS_ATOM_NET_WM_ALLOWED_ACTIONS,
|
||||||
TASKS_ATOM_NET_WM_DESKTOP,
|
TASKS_ATOM_NET_WM_DESKTOP,
|
||||||
TASKS_ATOM_NET_WM_ICON,
|
TASKS_ATOM_NET_WM_ICON,
|
||||||
TASKS_ATOM_NET_WM_NAME,
|
TASKS_ATOM_NET_WM_NAME,
|
||||||
|
@ -83,6 +94,17 @@ static const char * _tasks_atom[TASKS_ATOM_COUNT] =
|
||||||
"_NET_CLIENT_LIST",
|
"_NET_CLIENT_LIST",
|
||||||
"_NET_CLOSE_WINDOW",
|
"_NET_CLOSE_WINDOW",
|
||||||
"_NET_CURRENT_DESKTOP",
|
"_NET_CURRENT_DESKTOP",
|
||||||
|
"_NET_WM_ACTION_CHANGE_DESKTOP",
|
||||||
|
"_NET_WM_ACTION_CLOSE",
|
||||||
|
"_NET_WM_ACTION_MOVE",
|
||||||
|
"_NET_WM_ACTION_RESIZE",
|
||||||
|
"_NET_WM_ACTION_MINIMIZE",
|
||||||
|
"_NET_WM_ACTION_SHADE",
|
||||||
|
"_NET_WM_ACTION_STICK",
|
||||||
|
"_NET_WM_ACTION_MAXIMIZE_HORZ",
|
||||||
|
"_NET_WM_ACTION_MAXIMIZE_VERT",
|
||||||
|
"_NET_WM_ACTION_FULLSCREEN",
|
||||||
|
"_NET_WM_ALLOWED_ACTIONS",
|
||||||
"_NET_WM_DESKTOP",
|
"_NET_WM_DESKTOP",
|
||||||
"_NET_WM_ICON",
|
"_NET_WM_ICON",
|
||||||
"_NET_WM_NAME",
|
"_NET_WM_NAME",
|
||||||
|
@ -117,10 +139,19 @@ static void _tasks_do(Tasks * tasks);
|
||||||
|
|
||||||
/* callbacks */
|
/* callbacks */
|
||||||
static void _on_clicked(GtkWidget * widget, gpointer data);
|
static void _on_clicked(GtkWidget * widget, gpointer data);
|
||||||
static void _on_close(gpointer data);
|
|
||||||
static GdkFilterReturn _on_filter(GdkXEvent * xevent, GdkEvent * event,
|
static GdkFilterReturn _on_filter(GdkXEvent * xevent, GdkEvent * event,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
static gboolean _on_popup(gpointer data);
|
static gboolean _on_popup(gpointer data);
|
||||||
|
static void _on_popup_change_desktop(gpointer data);
|
||||||
|
static void _on_popup_close(gpointer data);
|
||||||
|
static void _on_popup_fullscreen(gpointer data);
|
||||||
|
static void _on_popup_maximize_horz(gpointer data);
|
||||||
|
static void _on_popup_maximize_vert(gpointer data);
|
||||||
|
static void _on_popup_minimize(gpointer data);
|
||||||
|
static void _on_popup_move(gpointer data);
|
||||||
|
static void _on_popup_resize(gpointer data);
|
||||||
|
static void _on_popup_shade(gpointer data);
|
||||||
|
static void _on_popup_stick(gpointer data);
|
||||||
static void _on_screen_changed(GtkWidget * widget, GdkScreen * previous,
|
static void _on_screen_changed(GtkWidget * widget, GdkScreen * previous,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
|
|
||||||
|
@ -619,31 +650,6 @@ static void _clicked_activate(Task * task)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* on_close */
|
|
||||||
static void _on_close(gpointer data)
|
|
||||||
{
|
|
||||||
Task * task = data;
|
|
||||||
GdkDisplay * display;
|
|
||||||
XEvent xev;
|
|
||||||
|
|
||||||
display = task->tasks->display;
|
|
||||||
memset(&xev, 0, sizeof(xev));
|
|
||||||
xev.xclient.type = ClientMessage;
|
|
||||||
xev.xclient.window = task->window;
|
|
||||||
xev.xclient.message_type = task->tasks->atom[
|
|
||||||
TASKS_ATOM_NET_CLOSE_WINDOW];
|
|
||||||
xev.xclient.format = 32;
|
|
||||||
xev.xclient.data.l[0] = gdk_x11_display_get_user_time(display);
|
|
||||||
xev.xclient.data.l[1] = 2;
|
|
||||||
gdk_error_trap_push();
|
|
||||||
XSendEvent(GDK_DISPLAY_XDISPLAY(display),
|
|
||||||
GDK_WINDOW_XWINDOW(task->tasks->root), False,
|
|
||||||
SubstructureNotifyMask | SubstructureRedirectMask,
|
|
||||||
&xev);
|
|
||||||
gdk_error_trap_pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* on_filter */
|
/* on_filter */
|
||||||
static GdkFilterReturn _on_filter(GdkXEvent * xevent, GdkEvent * event,
|
static GdkFilterReturn _on_filter(GdkXEvent * xevent, GdkEvent * event,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
|
@ -669,14 +675,59 @@ static GdkFilterReturn _on_filter(GdkXEvent * xevent, GdkEvent * event,
|
||||||
static gboolean _on_popup(gpointer data)
|
static gboolean _on_popup(gpointer data)
|
||||||
{
|
{
|
||||||
Task * task = data;
|
Task * task = data;
|
||||||
GtkWidget * menu;
|
unsigned long cnt = 0;
|
||||||
|
unsigned long * buf = NULL;
|
||||||
|
unsigned long i;
|
||||||
|
const struct {
|
||||||
|
TasksAtom atom;
|
||||||
|
void (*callback)(gpointer data);
|
||||||
|
char const * stock;
|
||||||
|
} items[] = {
|
||||||
|
{ TASKS_ATOM_NET_WM_ACTION_MOVE, _on_popup_move, "Move" },
|
||||||
|
{ TASKS_ATOM_NET_WM_ACTION_RESIZE, _on_popup_resize, "Resize" },
|
||||||
|
{ TASKS_ATOM_NET_WM_ACTION_MINIMIZE, _on_popup_minimize,
|
||||||
|
"Minimize" },
|
||||||
|
{ TASKS_ATOM_NET_WM_ACTION_SHADE, _on_popup_shade, "Shade" },
|
||||||
|
{ TASKS_ATOM_NET_WM_ACTION_STICK, _on_popup_stick, "Stick" },
|
||||||
|
{ TASKS_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ,
|
||||||
|
_on_popup_maximize_horz, "Maximize horizontally" },
|
||||||
|
{ TASKS_ATOM_NET_WM_ACTION_MAXIMIZE_VERT,
|
||||||
|
_on_popup_maximize_vert, "Maximize vertically" },
|
||||||
|
{ TASKS_ATOM_NET_WM_ACTION_FULLSCREEN, _on_popup_fullscreen,
|
||||||
|
GTK_STOCK_FULLSCREEN},
|
||||||
|
{ TASKS_ATOM_NET_WM_ACTION_CHANGE_DESKTOP,
|
||||||
|
_on_popup_change_desktop, "Change desktop" },
|
||||||
|
{ TASKS_ATOM_NET_WM_ACTION_CLOSE, _on_popup_close,
|
||||||
|
GTK_STOCK_CLOSE }
|
||||||
|
};
|
||||||
|
size_t j;
|
||||||
|
GtkWidget * menu = NULL;
|
||||||
GtkWidget * menuitem;
|
GtkWidget * menuitem;
|
||||||
|
|
||||||
menu = gtk_menu_new();
|
if(_tasks_get_window_property(task->tasks, task->window,
|
||||||
menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLOSE, NULL);
|
TASKS_ATOM_NET_WM_ALLOWED_ACTIONS, XA_ATOM,
|
||||||
g_signal_connect_swapped(G_OBJECT(menuitem), "activate", G_CALLBACK(
|
&cnt, (void*)&buf) != 0)
|
||||||
_on_close), task);
|
return FALSE;
|
||||||
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
|
for(i = 0; i < cnt; i++)
|
||||||
|
{
|
||||||
|
for(j = 0; j < sizeof(items) / sizeof(*items); j++)
|
||||||
|
if(buf[i] == task->tasks->atom[items[j].atom])
|
||||||
|
break;
|
||||||
|
if(j >= sizeof(items) / sizeof(*items))
|
||||||
|
continue;
|
||||||
|
if(items[j].atom == TASKS_ATOM_NET_WM_ACTION_CHANGE_DESKTOP)
|
||||||
|
continue; /* FIXME implement as a special case */
|
||||||
|
if(menu == NULL)
|
||||||
|
menu = gtk_menu_new();
|
||||||
|
menuitem = gtk_image_menu_item_new_from_stock(items[j].stock,
|
||||||
|
NULL); /* XXX they're not always stock */
|
||||||
|
g_signal_connect_swapped(G_OBJECT(menuitem), "activate",
|
||||||
|
G_CALLBACK(items[j].callback), task);
|
||||||
|
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
|
||||||
|
}
|
||||||
|
XFree(buf);
|
||||||
|
if(menu == NULL)
|
||||||
|
return FALSE;
|
||||||
gtk_widget_show_all(menu);
|
gtk_widget_show_all(menu);
|
||||||
gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, task, 2,
|
gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, task, 2,
|
||||||
gtk_get_current_event_time());
|
gtk_get_current_event_time());
|
||||||
|
@ -684,6 +735,94 @@ static gboolean _on_popup(gpointer data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* on_popup_change_desktop */
|
||||||
|
static void _on_popup_change_desktop(gpointer data)
|
||||||
|
{
|
||||||
|
/* FIXME implement */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* on_popup_close */
|
||||||
|
static void _on_popup_close(gpointer data)
|
||||||
|
{
|
||||||
|
Task * task = data;
|
||||||
|
GdkDisplay * display;
|
||||||
|
XEvent xev;
|
||||||
|
|
||||||
|
display = task->tasks->display;
|
||||||
|
memset(&xev, 0, sizeof(xev));
|
||||||
|
xev.xclient.type = ClientMessage;
|
||||||
|
xev.xclient.window = task->window;
|
||||||
|
xev.xclient.message_type = task->tasks->atom[
|
||||||
|
TASKS_ATOM_NET_CLOSE_WINDOW];
|
||||||
|
xev.xclient.format = 32;
|
||||||
|
xev.xclient.data.l[0] = gdk_x11_display_get_user_time(display);
|
||||||
|
xev.xclient.data.l[1] = 2;
|
||||||
|
gdk_error_trap_push();
|
||||||
|
XSendEvent(GDK_DISPLAY_XDISPLAY(display),
|
||||||
|
GDK_WINDOW_XWINDOW(task->tasks->root), False,
|
||||||
|
SubstructureNotifyMask | SubstructureRedirectMask,
|
||||||
|
&xev);
|
||||||
|
gdk_error_trap_pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* on_popup_fullscreen */
|
||||||
|
static void _on_popup_fullscreen(gpointer data)
|
||||||
|
{
|
||||||
|
/* FIXME implement */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* on_popup_maximize_hort */
|
||||||
|
static void _on_popup_maximize_horz(gpointer data)
|
||||||
|
{
|
||||||
|
/* FIXME implement */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* on_popup_maximize_vert */
|
||||||
|
static void _on_popup_maximize_vert(gpointer data)
|
||||||
|
{
|
||||||
|
/* FIXME implement */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* on_popup_minimize */
|
||||||
|
static void _on_popup_minimize(gpointer data)
|
||||||
|
{
|
||||||
|
/* FIXME implement */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* on_popup_move */
|
||||||
|
static void _on_popup_move(gpointer data)
|
||||||
|
{
|
||||||
|
/* FIXME implement */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* on_popup_resize */
|
||||||
|
static void _on_popup_resize(gpointer data)
|
||||||
|
{
|
||||||
|
/* FIXME implement */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* on_popup_shade */
|
||||||
|
static void _on_popup_shade(gpointer data)
|
||||||
|
{
|
||||||
|
/* FIXME implement */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* on_popup_stick */
|
||||||
|
static void _on_popup_stick(gpointer data)
|
||||||
|
{
|
||||||
|
/* FIXME implement */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* on_screen_changed */
|
/* on_screen_changed */
|
||||||
static void _on_screen_changed(GtkWidget * widget, GdkScreen * previous,
|
static void _on_screen_changed(GtkWidget * widget, GdkScreen * previous,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user