dockapps/wmnotify/src/dockapp.c
2014-10-05 19:18:49 +01:00

301 lines
9.4 KiB
C

/*
* dockapp.c -- routines for managing dockapp windows and icons.
*
* Copyright (C) 2003 Hugo Villeneuve <hugo@hugovil.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* Define filename_M */
#define DOCKAPP_M 1
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/xpm.h>
#include <X11/extensions/shape.h>
#include "common.h"
#include "dockapp.h"
#define XLIB_FAILURE 0
#define XLIB_SUCCESS 1
/* Specifies the border width */
#define BWIDTH 1
/* Width and height in pixels of Window Maker icons. */
#define ICON_SIZE 64
static void
CreateIconFromXpmData( char *pixmap_data[] )
{
int status;
dockapp.xpm_icon.attributes.valuemask |=
( XpmReturnPixels | XpmReturnExtensions );
/* Using the XPM library to read XPM data from the array in the included XPM
file. The 'shapemask' Pixmap variable is set to an additional 1-bit deep
pixmap that can then be used as a shape mask for the XShapeCombineMask()
function. */
status = XpmCreatePixmapFromData( dockapp.display, dockapp.root_win,
pixmap_data, &dockapp.xpm_icon.image,
&dockapp.xpm_icon.shapemask,
&dockapp.xpm_icon.attributes );
if( status != XpmSuccess ) {
fprintf( stderr, "%s: XpmCreatePixmapFromData() failed\n", PACKAGE );
ErrorLocation( __FILE__, __LINE__ );
exit( EXIT_FAILURE );
}
}
static Pixel
GetColor( char *name )
{
int status;
bool res;
XColor color;
XWindowAttributes attributes;
status = XGetWindowAttributes( dockapp.display, dockapp.root_win,
&attributes );
if( status == XLIB_FAILURE ) {
fprintf( stderr, "%s: XGetWindowAttributes() failed\n", PACKAGE );
ErrorLocation( __FILE__, __LINE__ );
exit( EXIT_FAILURE );
}
color.pixel = 0;
res = (bool) XParseColor( dockapp.display, attributes.colormap, name,
&color );
if( res == false ) {
fprintf( stderr, "%s: Can't parse %s.\n", PACKAGE, name );
ErrorLocation( __FILE__, __LINE__ );
exit( EXIT_FAILURE );
}
res = (bool) XAllocColor( dockapp.display, attributes.colormap, &color );
if( res == false ) {
fprintf( stderr, "%s: Can't allocate %s.\n", PACKAGE, name );
ErrorLocation( __FILE__, __LINE__ );
exit( EXIT_FAILURE );
}
return color.pixel;
}
static void
flush_expose( Window win )
{
XEvent dummy;
bool res = true;
while( res != false ) {
res = (bool) XCheckTypedWindowEvent( dockapp.display, win, Expose, &dummy );
}
}
void
RedrawWindow( void )
{
flush_expose( dockapp.iconwin );
(void) XCopyArea( dockapp.display, dockapp.xpm_icon.image, dockapp.iconwin,
dockapp.NormalGC, 0, 0, dockapp.xpm_icon.attributes.width,
dockapp.xpm_icon.attributes.height, 0, 0 );
flush_expose( dockapp.win );
(void) XCopyArea( dockapp.display, dockapp.xpm_icon.image, dockapp.win,
dockapp.NormalGC, 0, 0, dockapp.xpm_icon.attributes.width,
dockapp.xpm_icon.attributes.height, 0, 0 );
}
void
copyXPMArea( int x, int y, unsigned int sx, unsigned int sy, int dx, int dy )
{
(void) XCopyArea( dockapp.display, dockapp.xpm_icon.image,
dockapp.xpm_icon.image, dockapp.NormalGC, x, y, sx, sy,
dx, dy );
}
/*******************************************************************************
* New window creation and initialization for a Dockable Application
******************************************************************************/
void
InitDockAppWindow( int argc, char *argv[], char *pixmap_data[],
char *display_arg, char *geometry_arg )
{
XGCValues gcv;
XSizeHints size_hints;
XWMHints wm_hints;
int status;
int gravity = 0; /* Used to store the gravity value returned by XWMGeometry,
but not used. */
/* Opening a connection to the X server. */
dockapp.display = XOpenDisplay( display_arg );
if( dockapp.display == NULL ) {
fprintf( stderr, "%s: Can't open display: %s\n", PACKAGE,
XDisplayName( display_arg ) );
ErrorLocation( __FILE__, __LINE__ );
exit( EXIT_FAILURE );
}
dockapp.screen = DefaultScreen( dockapp.display );
dockapp.root_win = RootWindow( dockapp.display, dockapp.screen );
dockapp.d_depth = DefaultDepth( dockapp.display, dockapp.screen );
/* Create a window to hold the stuff */
size_hints.flags = USSize | USPosition;
size_hints.x = 0;
size_hints.y = 0;
/* Constructing window's geometry information. */
/* XWMGeometry() returns an 'int', but Xlib documentation doesn't explain
it's meaning. */
XWMGeometry( dockapp.display, dockapp.screen, geometry_arg, NULL, BWIDTH,
&size_hints, &size_hints.x, &size_hints.y, &size_hints.width,
&size_hints.height, &gravity );
size_hints.width = ICON_SIZE;
size_hints.height = ICON_SIZE;
dockapp.back_pix = GetColor("white");
dockapp.fore_pix = GetColor("black");
dockapp.win = XCreateSimpleWindow( dockapp.display, dockapp.root_win,
size_hints.x, size_hints.y,
(unsigned int) size_hints.width,
(unsigned int) size_hints.height,
BWIDTH, dockapp.fore_pix,
dockapp.back_pix );
dockapp.iconwin = XCreateSimpleWindow( dockapp.display, dockapp.win,
size_hints.x, size_hints.y,
(unsigned int) size_hints.width,
(unsigned int) size_hints.height,
BWIDTH, dockapp.fore_pix,
dockapp.back_pix );
/* Configuring Client to Window Manager Communications. */
/* WM_NORMAL_HINTS property: size hints for a window in it's normal state. */
/* Replaces the size hints for the WM_NORMAL_HINTS property on the specified
window. */
XSetWMNormalHints( dockapp.display, dockapp.win, &size_hints );
/* Setting the WM_CLASS property. */
{
char *app_name = argv[0];
XClassHint wm_class;
/* The res_name member contains the application name.
The res_class member contains the application class. */
/* The name set in this property may differ from the name set as WM_NAME.
That is, WM_NAME specifies what should be displayed in the title bar and,
therefore, can contain temporal information (for example, the name of a
file currently in an editor's buffer). On the other hand, the name
specified as part of WM_CLASS is the formal name of the application that
should be used when retrieving the application's resources from the
resource database. */
wm_class.res_name = app_name;
wm_class.res_class = app_name;
(void) XSetClassHint( dockapp.display, dockapp.win, &wm_class );
}
/* Setting the WM_NAME property.
This specifies what should be displayed in the title bar (usually the
application name). */
{
XTextProperty text_prop;
char *app_name = argv[0];
const int string_count = 1;
status = XStringListToTextProperty( &app_name, string_count, &text_prop );
if( status == 0 ) {
fprintf( stderr, "%s: XStringListToTextProperty() failed\n", PACKAGE );
ErrorLocation( __FILE__, __LINE__ );
exit( EXIT_FAILURE );
}
XSetWMName( dockapp.display, dockapp.win, &text_prop );
/* Freing the storage for the value field. */
(void) XFree( text_prop.value );
}
/* WM_HINTS --> Additional hints set by the client for use by the Window
Manager. */
/* XWMHints wm_hints; */
/* WithdrawnState, NormalState or IconicState. Must be set to WithdrawnState
for DockApp. */
wm_hints.flags = StateHint | IconWindowHint | IconPositionHint |
WindowGroupHint;
wm_hints.initial_state = WithdrawnState; /* Withdrawn, Normal */
wm_hints.icon_window = dockapp.iconwin;
wm_hints.icon_x = size_hints.x;
wm_hints.icon_y = size_hints.y;
wm_hints.window_group = dockapp.win;
(void) XSetWMHints( dockapp.display, dockapp.win, &wm_hints );
/* Sets the WM_COMMAND property. This sets the command and arguments used to
invoke the application. */
(void) XSetCommand( dockapp.display, dockapp.win, argv, argc );
/* ... */
(void) XSelectInput( dockapp.display, dockapp.win,
ButtonPressMask | ExposureMask | ButtonReleaseMask |
PointerMotionMask | StructureNotifyMask );
(void) XSelectInput( dockapp.display, dockapp.iconwin,
ButtonPressMask | ExposureMask | ButtonReleaseMask |
PointerMotionMask | StructureNotifyMask );
/* Create GC for drawing */
gcv.foreground = dockapp.fore_pix;
gcv.background = dockapp.back_pix;
gcv.graphics_exposures = 0;
dockapp.NormalGC = XCreateGC( dockapp.display, dockapp.root_win,
GCForeground | GCBackground |
GCGraphicsExposures, &gcv );
/* Convert XPM data to XImage */
CreateIconFromXpmData( pixmap_data );
XShapeCombineMask( dockapp.display, dockapp.win, ShapeBounding, 0, 0,
dockapp.xpm_icon.shapemask, ShapeSet );
XShapeCombineMask( dockapp.display, dockapp.iconwin, ShapeBounding, 0, 0,
dockapp.xpm_icon.shapemask, ShapeSet );
/* Making the new window visible. */
(void) XMapWindow( dockapp.display, dockapp.win );
}