193 lines
7.6 KiB
C
193 lines
7.6 KiB
C
|
#include "../config.h"
|
||
|
|
||
|
/*
|
||
|
Best viewed with vim5, using ts=4
|
||
|
|
||
|
wmgeneral was taken from wmppp.
|
||
|
|
||
|
It has a lot of routines which most of the wm* programs use.
|
||
|
|
||
|
------------------------------------------------------------
|
||
|
|
||
|
Author: Brad Jorsch, anomie@users.sourceforge.net
|
||
|
|
||
|
---
|
||
|
CHANGES:
|
||
|
---
|
||
|
15/08/2002 (Brad Jorsch, anomie@users.sourceforge.net)
|
||
|
* Pulled createXBMfromXPM into its own file, because it's the same in
|
||
|
both -gtk and -x11.
|
||
|
|
||
|
11/08/2002 (Brad Jorsch, anomie@users.sourceforge.net)
|
||
|
* This is based on wmgeneral-x11.c (formerly wmgeneral.c), it
|
||
|
implements a subset of the interface using Gtk+ 2.0
|
||
|
|
||
|
*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#include <gtk/gtk.h>
|
||
|
#include <gdk/gdkx.h>
|
||
|
|
||
|
#include "wmgeneral-gtk.h"
|
||
|
|
||
|
/******************/
|
||
|
/* Gtk+ Variables */
|
||
|
/******************/
|
||
|
|
||
|
static GtkWidget *dockwin, *iconwin;
|
||
|
static GdkPixmap *pixmap, *mask;
|
||
|
static GdkGC *pixmap_gc, *mask_gc;
|
||
|
static void (*click_func)(GdkEventButton *ev);
|
||
|
|
||
|
/******************************************************************************\
|
||
|
|* RedrawWindow *|
|
||
|
\******************************************************************************/
|
||
|
|
||
|
void RedrawWindow(void) {
|
||
|
gdk_draw_drawable(dockwin->window, pixmap_gc, pixmap, 0, 0, 0, 0, 64, 64);
|
||
|
gdk_draw_drawable(iconwin->window, pixmap_gc, pixmap, 0, 0, 0, 0, 64, 64);
|
||
|
}
|
||
|
|
||
|
static gint redraw_dock(gpointer d){
|
||
|
RedrawWindow();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/******************************************************************************\
|
||
|
|* RedrawWindowXY *|
|
||
|
\******************************************************************************/
|
||
|
|
||
|
void RedrawWindowXY(int x, int y) {
|
||
|
gdk_draw_drawable(dockwin->window, pixmap_gc, pixmap, x, y, 0, 0, 64, 64);
|
||
|
gdk_draw_drawable(iconwin->window, pixmap_gc, pixmap, x, y, 0, 0, 64, 64);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************\
|
||
|
|* copyXPMArea *|
|
||
|
\******************************************************************************/
|
||
|
|
||
|
void copyPixmapArea(int sx, int sy, int w, int h, int dx, int dy){
|
||
|
gdk_draw_drawable(pixmap, pixmap_gc, pixmap, sx, sy, dx, dy, w, h);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************\
|
||
|
|* copyXBMArea *|
|
||
|
\******************************************************************************/
|
||
|
|
||
|
void copyMaskArea(int sx, int sy, int w, int h, int dx, int dy){
|
||
|
gdk_draw_drawable(mask, mask_gc, mask, sx, sy, dx, dy, w, h);
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************\
|
||
|
|* setMaskXY *|
|
||
|
\******************************************************************************/
|
||
|
|
||
|
void setMaskXY(int x, int y) {
|
||
|
gtk_widget_shape_combine_mask(dockwin, mask, x, y);
|
||
|
gtk_widget_shape_combine_mask(iconwin, mask, x, y);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************\
|
||
|
|* setClickCallback *|
|
||
|
\******************************************************************************/
|
||
|
void setClickCallback(void (*func)(GdkEventButton *ev)){
|
||
|
click_func=func;
|
||
|
}
|
||
|
|
||
|
/******************************************************************************\
|
||
|
|* openXwindow *|
|
||
|
\******************************************************************************/
|
||
|
|
||
|
static GdkWindow *get_gdk_leader(GdkWindow *win){
|
||
|
GdkAtom atom, type;
|
||
|
gint len;
|
||
|
guchar *data;
|
||
|
GdkWindow *leader=NULL;
|
||
|
|
||
|
atom=gdk_atom_intern("WM_CLIENT_LEADER", TRUE);
|
||
|
type=gdk_atom_intern("WINDOW", TRUE);
|
||
|
if(atom==GDK_NONE || type==GDK_NONE) return NULL;
|
||
|
if(!gdk_property_get(win, atom, type, 0, 4, FALSE, NULL, NULL, &len, &data)) return NULL; if(len==4) leader=gdk_window_foreign_new(*(GdkNativeWindow *)data);
|
||
|
g_free(data);
|
||
|
return leader;
|
||
|
}
|
||
|
|
||
|
static GdkFilterReturn button_filter(XEvent *x, GdkEvent *ev, gpointer data){
|
||
|
/* Bleh, Gdk insists on trying to translate buttons 4-7 into Scroll events.
|
||
|
* Which would be ok, except for the part where it just _throws_ _away_ the
|
||
|
* releases! Damnit... So, we cheat and change any buttons >3 into
|
||
|
* button+4, and change it back in the click handler. */
|
||
|
if((x->type==ButtonPress || x->type==ButtonRelease) && x->xbutton.button>3){
|
||
|
x->xbutton.button+=4;
|
||
|
}
|
||
|
return GDK_FILTER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
static void dock_click(GtkWidget *w, GdkEventButton *ev, gpointer d){
|
||
|
if(ev->button>7) ev->button-=4;
|
||
|
if(click_func!=NULL) click_func(ev);
|
||
|
}
|
||
|
|
||
|
#define die(args...) { fprintf(stderr, args); exit(1); }
|
||
|
|
||
|
void openDockWindow(int argc, char *argv[], char *pixmap_bytes[], char *pixmask_bits, int pixmask_width, int pixmask_height){
|
||
|
GdkColormap *cmap;
|
||
|
GdkColor white, black;
|
||
|
GdkWindow *leader;
|
||
|
XWMHints hints;
|
||
|
|
||
|
click_func=NULL;
|
||
|
if((dockwin=gtk_window_new(GTK_WINDOW_TOPLEVEL))==NULL) die("Couldn't create window");
|
||
|
if((iconwin=gtk_window_new(GTK_WINDOW_TOPLEVEL))==NULL) die("Couldn't create window");
|
||
|
gtk_widget_set_size_request(dockwin, 64, 64);
|
||
|
gtk_widget_set_size_request(iconwin, 64, 64);
|
||
|
gtk_widget_set_app_paintable(dockwin, TRUE);
|
||
|
gtk_widget_set_app_paintable(iconwin, TRUE);
|
||
|
gtk_widget_add_events(dockwin, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
|
||
|
gtk_widget_add_events(iconwin, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
|
||
|
g_signal_connect(G_OBJECT(dockwin), "expose-event", G_CALLBACK(redraw_dock), NULL);
|
||
|
g_signal_connect(G_OBJECT(iconwin), "expose-event", G_CALLBACK(redraw_dock), NULL);
|
||
|
g_signal_connect(G_OBJECT(dockwin), "button-press-event", G_CALLBACK(dock_click), NULL);
|
||
|
g_signal_connect(G_OBJECT(iconwin), "button-press-event", G_CALLBACK(dock_click), NULL);
|
||
|
g_signal_connect(G_OBJECT(dockwin), "button-release-event", G_CALLBACK(dock_click), NULL);
|
||
|
g_signal_connect(G_OBJECT(iconwin), "button-release-event", G_CALLBACK(dock_click), NULL);
|
||
|
g_signal_connect(G_OBJECT(dockwin), "destroy", G_CALLBACK(exit), NULL);
|
||
|
g_signal_connect(G_OBJECT(iconwin), "destroy", G_CALLBACK(exit), NULL);
|
||
|
gtk_widget_realize(dockwin);
|
||
|
gtk_widget_realize(iconwin);
|
||
|
gdk_window_add_filter(dockwin->window, (GdkFilterFunc)button_filter, NULL);
|
||
|
gdk_window_add_filter(iconwin->window, (GdkFilterFunc)button_filter, NULL);
|
||
|
if((leader=get_gdk_leader(dockwin->window))==NULL) die("Couldn't obtain Gdk leader window");
|
||
|
gdk_window_set_icon(leader, iconwin->window, NULL, NULL);
|
||
|
gdk_window_reparent(iconwin->window, leader, 0, 0);
|
||
|
gdk_window_unref(leader);
|
||
|
|
||
|
hints.initial_state = WithdrawnState;
|
||
|
hints.flags = StateHint;
|
||
|
XSetWMHints(GDK_DISPLAY(), GDK_WINDOW_XWINDOW(dockwin->window), &hints);
|
||
|
|
||
|
cmap=gdk_colormap_get_system();
|
||
|
white.red=65535;
|
||
|
white.green=65535;
|
||
|
white.blue=65535;
|
||
|
black.red=0;
|
||
|
black.green=0;
|
||
|
black.blue=0;
|
||
|
gdk_color_alloc(cmap, &white);
|
||
|
gdk_color_alloc(cmap, &black);
|
||
|
mask=gdk_pixmap_create_from_data(NULL, pixmask_bits, pixmask_width, pixmask_height, 1, &white, &black);
|
||
|
pixmap=gdk_pixmap_colormap_create_from_xpm_d(NULL, cmap, NULL, NULL, pixmap_bytes);
|
||
|
|
||
|
pixmap_gc=gdk_gc_new(iconwin->window);
|
||
|
mask_gc=gdk_gc_new(mask);
|
||
|
|
||
|
setMaskXY(0, 0);
|
||
|
RedrawWindow();
|
||
|
|
||
|
gtk_widget_show(iconwin);
|
||
|
gtk_widget_show(dockwin);
|
||
|
gdk_window_withdraw(dockwin->window);
|
||
|
}
|