1998-12-11 Federico Mena Quintero <federico@nuclecu.unam.mx>
Wheeeee! Desktop icons can be selected by rubberbanding. You need Englightenment to do this, as so far it seems to be the only WM with support for the _WIN_DESKTOP_BUTTON_PROXY property. * gdesktop.c (click_proxy_filter): New event filter for button presses and releases on the root window. (click_proxy_button_press): New function to handle button presses on the desktop. (click_proxy_button_release): New function to handle button releases on the desktop. (click_proxy_motion): New function to handle rubberbanding motion on the desktop. (setup_xdnd_proxy): Flush the server after ungrabbing it. (find_click_proxy_window): Flush the server after ungrabbing it. (store_temp_selection): Stores the temporary selection to the master selection, or viceversa. This is needed for dynamic updating while the user rubberbands. (update_drag_selection): New function to update the selection while the user is rubberbanding on the desktop. (icon_is_in_area): New function to see if an icon is inside the rubberbanding area. * gdesktop-icon.h: Added fields for querying the icon and text position and size. * gdesktop-icon.c (desktop_icon_reshape): Set the position and size fields as computed for layout.
Этот коммит содержится в:
родитель
3c8529fac4
Коммит
741d37e4eb
@ -1,3 +1,33 @@
|
|||||||
|
1998-12-11 Federico Mena Quintero <federico@nuclecu.unam.mx>
|
||||||
|
|
||||||
|
Wheeeee! Desktop icons can be selected by rubberbanding. You
|
||||||
|
need Englightenment to do this, as so far it seems to be the only
|
||||||
|
WM with support for the _WIN_DESKTOP_BUTTON_PROXY property.
|
||||||
|
|
||||||
|
* gdesktop.c (click_proxy_filter): New event filter for button
|
||||||
|
presses and releases on the root window.
|
||||||
|
(click_proxy_button_press): New function to handle button presses
|
||||||
|
on the desktop.
|
||||||
|
(click_proxy_button_release): New function to handle button
|
||||||
|
releases on the desktop.
|
||||||
|
(click_proxy_motion): New function to handle rubberbanding motion
|
||||||
|
on the desktop.
|
||||||
|
(setup_xdnd_proxy): Flush the server after ungrabbing it.
|
||||||
|
(find_click_proxy_window): Flush the server after ungrabbing it.
|
||||||
|
(store_temp_selection): Stores the temporary selection to the
|
||||||
|
master selection, or viceversa. This is needed for dynamic
|
||||||
|
updating while the user rubberbands.
|
||||||
|
(update_drag_selection): New function to update the selection
|
||||||
|
while the user is rubberbanding on the desktop.
|
||||||
|
(icon_is_in_area): New function to see if an icon is inside the
|
||||||
|
rubberbanding area.
|
||||||
|
|
||||||
|
* gdesktop-icon.h: Added fields for querying the icon and text
|
||||||
|
position and size.
|
||||||
|
|
||||||
|
* gdesktop-icon.c (desktop_icon_reshape): Set the position and
|
||||||
|
size fields as computed for layout.
|
||||||
|
|
||||||
1998-12-11 Owen Taylor <otaylor@redhat.com>
|
1998-12-11 Owen Taylor <otaylor@redhat.com>
|
||||||
|
|
||||||
* gdesktop.c (editing_started): Grab on the window for the
|
* gdesktop.c (editing_started): Grab on the window for the
|
||||||
|
@ -407,6 +407,16 @@ desktop_icon_reshape (DesktopIcon *dicon)
|
|||||||
|
|
||||||
gtk_widget_set_usize (GTK_WIDGET (dicon), dicon->width, dicon->height);
|
gtk_widget_set_usize (GTK_WIDGET (dicon), dicon->width, dicon->height);
|
||||||
create_window_shape (dicon, icon_width, icon_height, text_width, text_height);
|
create_window_shape (dicon, icon_width, icon_height, text_width, text_height);
|
||||||
|
|
||||||
|
dicon->icon_x = (int) ((dicon->width - icon_width) / 2.0 + 0.5);
|
||||||
|
dicon->icon_y = 0;
|
||||||
|
dicon->icon_w = icon_width;
|
||||||
|
dicon->icon_h = icon_height;
|
||||||
|
|
||||||
|
dicon->text_x = x1;
|
||||||
|
dicon->text_y = y1;
|
||||||
|
dicon->text_w = text_width;
|
||||||
|
dicon->text_h = text_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,6 +40,11 @@ struct _DesktopIcon {
|
|||||||
|
|
||||||
int width, height; /* Total size of the window */
|
int width, height; /* Total size of the window */
|
||||||
|
|
||||||
|
int icon_x, icon_y; /* Icon offsets */
|
||||||
|
int icon_w, icon_h; /* Icon size */
|
||||||
|
int text_x, text_y; /* Text offsets */
|
||||||
|
int text_w, text_h; /* Text size */
|
||||||
|
|
||||||
int w_changed_id; /* Signal connection ID for "width_changed" from the icon text item */
|
int w_changed_id; /* Signal connection ID for "width_changed" from the icon text item */
|
||||||
int h_changed_id; /* Signal connection ID for "height_changed" from the icon text item */
|
int h_changed_id; /* Signal connection ID for "height_changed" from the icon text item */
|
||||||
};
|
};
|
||||||
|
341
gnome/gdesktop.c
341
gnome/gdesktop.c
@ -50,14 +50,15 @@
|
|||||||
|
|
||||||
/* This structure defines the information carried by a desktop icon */
|
/* This structure defines the information carried by a desktop icon */
|
||||||
struct desktop_icon_info {
|
struct desktop_icon_info {
|
||||||
GtkWidget *dicon; /* The desktop icon widget */
|
GtkWidget *dicon; /* The desktop icon widget */
|
||||||
int x, y; /* Position in the desktop */
|
int x, y; /* Position in the desktop */
|
||||||
int slot; /* Index of the slot the icon is in, or -1 for none */
|
int slot; /* Index of the slot the icon is in, or -1 for none */
|
||||||
char *filename; /* The file this icon refers to (relative to the desktop_directory) */
|
char *filename; /* The file this icon refers to (relative to the desktop_directory) */
|
||||||
int selected : 1; /* Is the icon selected? */
|
int selected : 1; /* Is the icon selected? */
|
||||||
int finishing_selection : 1; /* Flag set while we are releasing button
|
int tmp_selected : 1; /* Temp storage for original selection while rubberbanding */
|
||||||
* after selecting in the text
|
int finishing_selection : 1; /* Flag set while we are releasing
|
||||||
*/
|
* button after selecting in the text
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
struct layout_slot {
|
struct layout_slot {
|
||||||
@ -124,6 +125,20 @@ static int dnd_select_icon_pending;
|
|||||||
static GdkWindow *click_proxy_gdk_window;
|
static GdkWindow *click_proxy_gdk_window;
|
||||||
static GtkWidget *click_proxy_invisible;
|
static GtkWidget *click_proxy_invisible;
|
||||||
|
|
||||||
|
/* GC for drawing the rubberband rectangle */
|
||||||
|
static GdkGC *click_gc;
|
||||||
|
|
||||||
|
/* Starting click position and event state for rubberbanding on the desktop */
|
||||||
|
static int click_start_x;
|
||||||
|
static int click_start_y;
|
||||||
|
static int click_start_state;
|
||||||
|
|
||||||
|
/* Current mouse position for rubberbanding on the desktop */
|
||||||
|
static int click_current_x;
|
||||||
|
static int click_current_y;
|
||||||
|
|
||||||
|
static int click_dragging;
|
||||||
|
|
||||||
|
|
||||||
static struct desktop_icon_info *desktop_icon_info_new (char *filename, int auto_pos, int xpos, int ypos);
|
static struct desktop_icon_info *desktop_icon_info_new (char *filename, int auto_pos, int xpos, int ypos);
|
||||||
static void desktop_icon_info_free (struct desktop_icon_info *dii);
|
static void desktop_icon_info_free (struct desktop_icon_info *dii);
|
||||||
@ -971,8 +986,6 @@ icon_drag_data_received (GtkWidget *widget, GdkDragContext *context, gint x, gin
|
|||||||
char *filename;
|
char *filename;
|
||||||
file_entry *fe;
|
file_entry *fe;
|
||||||
|
|
||||||
printf ("Here!\n");
|
|
||||||
|
|
||||||
dii = user_data;
|
dii = user_data;
|
||||||
filename = g_concat_dir_and_file (desktop_directory, dii->filename);
|
filename = g_concat_dir_and_file (desktop_directory, dii->filename);
|
||||||
|
|
||||||
@ -1234,6 +1247,7 @@ setup_xdnd_proxy (guint32 xid, GdkWindow *proxy_window)
|
|||||||
gdk_error_warnings = old_warnings;
|
gdk_error_warnings = old_warnings;
|
||||||
|
|
||||||
XUngrabServer (GDK_DISPLAY ());
|
XUngrabServer (GDK_DISPLAY ());
|
||||||
|
gdk_flush ();
|
||||||
|
|
||||||
if (!proxy) {
|
if (!proxy) {
|
||||||
/* Mark our window as a valid proxy window with a XdndProxy
|
/* Mark our window as a valid proxy window with a XdndProxy
|
||||||
@ -1446,6 +1460,7 @@ find_click_proxy_window (void)
|
|||||||
gdk_error_warnings = old_warnings;
|
gdk_error_warnings = old_warnings;
|
||||||
|
|
||||||
XUngrabServer (GDK_DISPLAY ());
|
XUngrabServer (GDK_DISPLAY ());
|
||||||
|
gdk_flush ();
|
||||||
|
|
||||||
if (proxy)
|
if (proxy)
|
||||||
proxy_gdk_window = gdk_window_foreign_new (proxy);
|
proxy_gdk_window = gdk_window_foreign_new (proxy);
|
||||||
@ -1455,18 +1470,277 @@ find_click_proxy_window (void)
|
|||||||
return proxy_gdk_window;
|
return proxy_gdk_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handles events on the root window via the click_proxy_gdk_window */
|
/* Executes the popup menu for the desktop */
|
||||||
static gint
|
static void
|
||||||
click_proxy_event (GtkWidget *widget, GdkEvent *event, gpointer data)
|
desktop_popup (GdkEventButton *event)
|
||||||
{
|
{
|
||||||
printf ("Click proxy event %d\n", event->type);
|
printf ("FIXME: display desktop popup menu\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draws the rubberband rectangle for selecting icons on the desktop */
|
||||||
|
static void
|
||||||
|
draw_rubberband (int x, int y)
|
||||||
|
{
|
||||||
|
int x1, y1, x2, y2;
|
||||||
|
|
||||||
|
if (click_start_x < x) {
|
||||||
|
x1 = click_start_x;
|
||||||
|
x2 = x;
|
||||||
|
} else {
|
||||||
|
x1 = x;
|
||||||
|
x2 = click_start_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (click_start_y < y) {
|
||||||
|
y1 = click_start_y;
|
||||||
|
y2 = y;
|
||||||
|
} else {
|
||||||
|
y1 = y;
|
||||||
|
y2 = click_start_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
gdk_draw_rectangle (GDK_ROOT_PARENT (), click_gc, FALSE, x1, y1, x2 - x1, y2 - y1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stores dii->selected into dii->tmp_selected to keep the original selection
|
||||||
|
* around while the user is rubberbanding.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
store_temp_selection (void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
GList *l;
|
||||||
|
struct desktop_icon_info *dii;
|
||||||
|
|
||||||
|
for (i = 0; i < (layout_cols * layout_rows); i++)
|
||||||
|
for (l = layout_slots[i].icons; l; l = l->next) {
|
||||||
|
dii = l->data;
|
||||||
|
|
||||||
|
dii->tmp_selected = dii->selected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns TRUE if the specified icon is at least partially inside the specified
|
||||||
|
* area, or FALSE otherwise.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
icon_is_in_area (struct desktop_icon_info *dii, int x1, int y1, int x2, int y2)
|
||||||
|
{
|
||||||
|
DesktopIcon *dicon;
|
||||||
|
|
||||||
|
dicon = DESKTOP_ICON (dii->dicon);
|
||||||
|
|
||||||
|
/* FIXME: this only intersects the rectangle with the icon image's
|
||||||
|
* bounds. Doing the "hard" intersection with the actual shape of the
|
||||||
|
* image is left as an exercise to the reader.
|
||||||
|
*/
|
||||||
|
|
||||||
|
x1 -= dii->x;
|
||||||
|
y1 -= dii->y;
|
||||||
|
x2 -= dii->x;
|
||||||
|
y2 -= dii->y;
|
||||||
|
|
||||||
|
if (x1 < dicon->icon_x + dicon->icon_w - 1
|
||||||
|
&& x2 > dicon->icon_x
|
||||||
|
&& y1 < dicon->icon_y + dicon->icon_h - 1
|
||||||
|
&& y2 > dicon->icon_y)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (x1 < dicon->text_x + dicon->text_w - 1
|
||||||
|
&& x2 > dicon->text_x
|
||||||
|
&& y1 < dicon->text_y + dicon->text_h - 1
|
||||||
|
&& y2 > dicon->text_y)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update the selection being rubberbanded. It selects or unselects the icons
|
||||||
|
* as appropriate.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
update_drag_selection (int x, int y)
|
||||||
|
{
|
||||||
|
int x1, y1, x2, y2;
|
||||||
|
int i;
|
||||||
|
GList *l;
|
||||||
|
struct desktop_icon_info *dii;
|
||||||
|
int additive, invert, in_area;
|
||||||
|
|
||||||
|
if (click_start_x < x) {
|
||||||
|
x1 = click_start_x;
|
||||||
|
x2 = x;
|
||||||
|
} else {
|
||||||
|
x1 = x;
|
||||||
|
x2 = click_start_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (click_start_y < y) {
|
||||||
|
y1 = click_start_y;
|
||||||
|
y2 = y;
|
||||||
|
} else {
|
||||||
|
y1 = y;
|
||||||
|
y2 = click_start_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Select or unselect icons as appropriate */
|
||||||
|
|
||||||
|
additive = click_start_state & GDK_SHIFT_MASK;
|
||||||
|
invert = click_start_state & GDK_CONTROL_MASK;
|
||||||
|
|
||||||
|
for (i = 0; i < (layout_cols * layout_rows); i++)
|
||||||
|
for (l = layout_slots[i].icons; l; l = l->next) {
|
||||||
|
dii = l->data;
|
||||||
|
|
||||||
|
in_area = icon_is_in_area (dii, x1, y1, x2, y2);
|
||||||
|
|
||||||
|
if (in_area) {
|
||||||
|
if (invert) {
|
||||||
|
if (dii->selected == dii->tmp_selected) {
|
||||||
|
desktop_icon_select (DESKTOP_ICON (dii->dicon), !dii->selected);
|
||||||
|
dii->selected = !dii->selected;
|
||||||
|
}
|
||||||
|
} else if (additive) {
|
||||||
|
if (!dii->selected) {
|
||||||
|
desktop_icon_select (DESKTOP_ICON (dii->dicon), TRUE);
|
||||||
|
dii->selected = TRUE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!dii->selected) {
|
||||||
|
desktop_icon_select (DESKTOP_ICON (dii->dicon), TRUE);
|
||||||
|
dii->selected = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (dii->selected != dii->tmp_selected) {
|
||||||
|
desktop_icon_select (DESKTOP_ICON (dii->dicon), dii->tmp_selected);
|
||||||
|
dii->selected = dii->tmp_selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handles button presses on the root window via the click_proxy_gdk_window */
|
||||||
|
static gint
|
||||||
|
click_proxy_button_press (GtkWidget *widget, GdkEventButton *event, gpointer data)
|
||||||
|
{
|
||||||
|
if (event->button == 1) {
|
||||||
|
click_start_x = event->x;
|
||||||
|
click_start_y = event->y;
|
||||||
|
click_start_state = event->state;
|
||||||
|
|
||||||
|
XGrabServer (GDK_DISPLAY ());
|
||||||
|
|
||||||
|
gdk_pointer_grab (GDK_ROOT_PARENT (),
|
||||||
|
FALSE,
|
||||||
|
GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
event->time);
|
||||||
|
|
||||||
|
/* If no modifiers are pressed, we unselect all the icons */
|
||||||
|
|
||||||
|
if ((click_start_state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) == 0)
|
||||||
|
unselect_all (NULL);
|
||||||
|
|
||||||
|
store_temp_selection (); /* Save the original selection */
|
||||||
|
|
||||||
|
draw_rubberband (event->x, event->y);
|
||||||
|
click_current_x = event->x;
|
||||||
|
click_current_y = event->y;
|
||||||
|
click_dragging = TRUE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
} else if (event->button == 3) {
|
||||||
|
desktop_popup (event);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handles button releases on the root window via the click_proxy_gdk_window */
|
||||||
|
static gint
|
||||||
|
click_proxy_button_release (GtkWidget *widget, GdkEventButton *event, gpointer data)
|
||||||
|
{
|
||||||
|
if (!click_dragging || event->button != 1)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
draw_rubberband (click_current_x, click_current_y);
|
||||||
|
gdk_pointer_ungrab (event->time);
|
||||||
|
click_dragging = FALSE;
|
||||||
|
|
||||||
|
update_drag_selection (event->x, event->y);
|
||||||
|
|
||||||
|
XUngrabServer (GDK_DISPLAY ());
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handles motion events when dragging the icon-selection rubberband on the desktop */
|
||||||
|
static gint
|
||||||
|
click_proxy_motion (GtkWidget *widget, GdkEventMotion *event, gpointer data)
|
||||||
|
{
|
||||||
|
if (!click_dragging)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
draw_rubberband (click_current_x, click_current_y);
|
||||||
|
draw_rubberband (event->x, event->y);
|
||||||
|
update_drag_selection (event->x, event->y);
|
||||||
|
click_current_x = event->x;
|
||||||
|
click_current_y = event->y;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Filter that translates proxied events from virtual root windows into normal
|
||||||
|
* Gdk events for the click_proxy_invisible widget.
|
||||||
|
*/
|
||||||
|
static GdkFilterReturn
|
||||||
|
click_proxy_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data)
|
||||||
|
{
|
||||||
|
XEvent *xev;
|
||||||
|
|
||||||
|
xev = xevent;
|
||||||
|
|
||||||
|
switch (xev->type) {
|
||||||
|
case ButtonPress:
|
||||||
|
case ButtonRelease:
|
||||||
|
if (xev->type == ButtonPress)
|
||||||
|
event->button.type = GDK_BUTTON_PRESS;
|
||||||
|
else
|
||||||
|
event->button.type = GDK_BUTTON_RELEASE;
|
||||||
|
|
||||||
|
gdk_window_ref (click_proxy_gdk_window);
|
||||||
|
|
||||||
|
event->button.window = click_proxy_gdk_window;
|
||||||
|
event->button.send_event = xev->xbutton.send_event;
|
||||||
|
event->button.time = xev->xbutton.time;
|
||||||
|
event->button.x = xev->xbutton.x;
|
||||||
|
event->button.y = xev->xbutton.y;
|
||||||
|
event->button.state = xev->xbutton.state;
|
||||||
|
event->button.button = xev->xbutton.button;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return GDK_FILTER_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GDK_FILTER_TRANSLATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define gray50_width 2
|
||||||
|
#define gray50_height 2
|
||||||
|
static char gray50_bits[] = {
|
||||||
|
0x02, 0x01, };
|
||||||
|
|
||||||
/* Sets up the window manager proxy window to receive clicks on the desktop root window */
|
/* Sets up the window manager proxy window to receive clicks on the desktop root window */
|
||||||
static void
|
static void
|
||||||
setup_desktop_clicks (void)
|
setup_desktop_clicks (void)
|
||||||
{
|
{
|
||||||
|
GdkColormap *cmap;
|
||||||
|
GdkColor color;
|
||||||
|
GdkBitmap *stipple;
|
||||||
|
|
||||||
click_proxy_gdk_window = find_click_proxy_window ();
|
click_proxy_gdk_window = find_click_proxy_window ();
|
||||||
if (!click_proxy_gdk_window) {
|
if (!click_proxy_gdk_window) {
|
||||||
g_warning ("Root window clicks will not work as no GNOME-compliant window manager could be found!");
|
g_warning ("Root window clicks will not work as no GNOME-compliant window manager could be found!");
|
||||||
@ -1475,15 +1749,48 @@ setup_desktop_clicks (void)
|
|||||||
|
|
||||||
click_proxy_invisible = gtk_invisible_new ();
|
click_proxy_invisible = gtk_invisible_new ();
|
||||||
gtk_widget_show (click_proxy_invisible);
|
gtk_widget_show (click_proxy_invisible);
|
||||||
gdk_window_set_user_data (click_proxy_gdk_window, click_proxy_invisible); /* make it send events to us */
|
|
||||||
|
/* Make the proxy and the root windows send events to the invisible proxy widget */
|
||||||
|
|
||||||
|
gdk_window_set_user_data (click_proxy_gdk_window, click_proxy_invisible);
|
||||||
|
gdk_window_set_user_data (GDK_ROOT_PARENT (), click_proxy_invisible);
|
||||||
|
|
||||||
|
/* Add our filter to translate virtual root window events into Gdk events */
|
||||||
|
|
||||||
|
gdk_window_add_filter (GDK_ROOT_PARENT (), click_proxy_filter, NULL);
|
||||||
|
|
||||||
/* The proxy window for clicks sends us events as SubstructureNotify things */
|
/* The proxy window for clicks sends us events as SubstructureNotify things */
|
||||||
|
|
||||||
XSelectInput (GDK_DISPLAY (), GDK_WINDOW_XWINDOW (click_proxy_gdk_window), SubstructureNotifyMask);
|
XSelectInput (GDK_DISPLAY (), GDK_WINDOW_XWINDOW (click_proxy_gdk_window), SubstructureNotifyMask);
|
||||||
|
|
||||||
gtk_signal_connect (GTK_OBJECT (click_proxy_invisible), "event",
|
gtk_signal_connect (GTK_OBJECT (click_proxy_invisible), "button_press_event",
|
||||||
(GtkSignalFunc) click_proxy_event,
|
(GtkSignalFunc) click_proxy_button_press,
|
||||||
NULL);
|
NULL);
|
||||||
|
gtk_signal_connect (GTK_OBJECT (click_proxy_invisible), "button_release_event",
|
||||||
|
(GtkSignalFunc) click_proxy_button_release,
|
||||||
|
NULL);
|
||||||
|
gtk_signal_connect (GTK_OBJECT (click_proxy_invisible), "motion_notify_event",
|
||||||
|
(GtkSignalFunc) click_proxy_motion,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* Create the GC to paint the rubberband rectangle */
|
||||||
|
|
||||||
|
click_gc = gdk_gc_new (GDK_ROOT_PARENT ());
|
||||||
|
|
||||||
|
cmap = gdk_window_get_colormap (GDK_ROOT_PARENT ());
|
||||||
|
|
||||||
|
gdk_color_white (cmap, &color);
|
||||||
|
if (color.pixel == 0)
|
||||||
|
gdk_color_black (cmap, &color);
|
||||||
|
|
||||||
|
gdk_gc_set_foreground (click_gc, &color);
|
||||||
|
gdk_gc_set_function (click_gc, GDK_XOR);
|
||||||
|
|
||||||
|
gdk_gc_set_fill (click_gc, GDK_STIPPLED);
|
||||||
|
|
||||||
|
stipple = gdk_bitmap_create_from_data (NULL, gray50_bits, gray50_width, gray50_height);
|
||||||
|
gdk_gc_set_stipple (click_gc, stipple);
|
||||||
|
gdk_bitmap_unref (stipple);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user