~ubuntu-branches/ubuntu/maverick/libaosd/maverick

« back to all changes in this revision

Viewing changes to libaosd/aosd-internal.c

  • Committer: Bazaar Package Importer
  • Author(s): William Pitcock
  • Date: 2007-11-30 07:42:21 UTC
  • Revision ID: james.westby@ubuntu.com-20071130074221-8yt6spn1ns6rfw7e
Tags: upstream-0.1.3
ImportĀ upstreamĀ versionĀ 0.1.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* aosd -- OSD with transparency, cairo, and pango.
 
2
 *
 
3
 * Copyright (C) 2006 Evan Martin <martine@danga.com>
 
4
 *
 
5
 * With further development by Giacomo Lozito <james@develia.org>
 
6
 * - added real transparency with X Composite Extension
 
7
 * - added mouse event handling on OSD window
 
8
 * - added/changed some other stuff
 
9
 */
 
10
 
 
11
#include "config.h"
 
12
 
 
13
#include <stdio.h>
 
14
#include <stdlib.h>
 
15
 
 
16
#include <X11/Xlib.h>
 
17
#include <X11/Xatom.h>
 
18
 
 
19
#ifdef HAVE_XCOMPOSITE
 
20
#include <X11/extensions/Xrender.h>
 
21
#include <X11/extensions/Xcomposite.h>
 
22
#endif
 
23
 
 
24
#include "aosd-internal.h"
 
25
 
 
26
void
 
27
make_window(Aosd* aosd)
 
28
{
 
29
  Display* dsp = aosd->display;
 
30
  Window root_win = aosd->root_win;
 
31
 
 
32
  if (aosd->win != None)
 
33
  {
 
34
    if (aosd->background.set)
 
35
    {
 
36
      XFreePixmap(dsp, aosd->background.pixmap);
 
37
      aosd->background.set = 0;
 
38
    }
 
39
 
 
40
    if (aosd->colormap != None)
 
41
    {
 
42
      XFreeColormap(dsp, aosd->colormap);
 
43
      aosd->colormap = None;
 
44
    }
 
45
 
 
46
    XDestroyWindow(dsp, aosd->win);
 
47
    aosd->win = None;
 
48
  }
 
49
 
 
50
  if (root_win == None)
 
51
    return;
 
52
 
 
53
  XSetWindowAttributes att;
 
54
 
 
55
  att.backing_store = WhenMapped;
 
56
  att.background_pixel = 0x0;
 
57
  att.border_pixel = 0;
 
58
  att.background_pixmap = None;
 
59
  att.colormap = None;
 
60
  att.save_under = True;
 
61
  att.event_mask = ExposureMask | StructureNotifyMask | ButtonPressMask;
 
62
  att.override_redirect = True;
 
63
 
 
64
  if (aosd->mode == TRANSPARENCY_COMPOSITE)
 
65
  {
 
66
#ifdef HAVE_XCOMPOSITE
 
67
    Visual* visual = NULL;
 
68
    if (composite_check_ext_and_mgr(dsp, aosd->screen_num) &&
 
69
        (visual = composite_find_argb_visual(dsp, aosd->screen_num)) != NULL)
 
70
    {
 
71
      aosd->visual = visual;
 
72
      aosd->colormap = att.colormap =
 
73
        XCreateColormap(dsp, root_win, visual, AllocNone);
 
74
      aosd->win = XCreateWindow(dsp, root_win,
 
75
          -1, -1, 1, 1, 0, 32, InputOutput, visual,
 
76
          CWBackingStore | CWBackPixel | CWBackPixmap | CWBorderPixel |
 
77
          CWColormap | CWEventMask | CWSaveUnder | CWOverrideRedirect,
 
78
          &att);
 
79
    }
 
80
    else
 
81
#endif
 
82
    {
 
83
      aosd->mode = TRANSPARENCY_FAKE;
 
84
      make_window(aosd);
 
85
      return;
 
86
    }
 
87
  }
 
88
  else
 
89
  {
 
90
    aosd->win = XCreateWindow(dsp, root_win,
 
91
        -1, -1, 1, 1, 0, CopyFromParent, InputOutput, CopyFromParent,
 
92
        CWBackingStore | CWBackPixel | CWBackPixmap | CWBorderPixel |
 
93
        CWEventMask | CWSaveUnder | CWOverrideRedirect, &att);
 
94
  }
 
95
 
 
96
  set_window_properties(dsp, aosd->win);
 
97
  if (aosd->width && aosd->height)
 
98
    aosd_set_geometry(aosd, aosd->x, aosd->y, aosd->width, aosd->height);
 
99
}
 
100
 
 
101
Pixmap
 
102
take_snapshot(Aosd* aosd)
 
103
{
 
104
  Display* dsp = aosd->display;
 
105
  Window root_win = aosd->root_win, win = aosd->win;
 
106
  int width = aosd->width, height = aosd->height;
 
107
  int scr = aosd->screen_num;
 
108
  Pixmap pixmap;
 
109
  GC gc;
 
110
 
 
111
  /* create a pixmap to hold the screenshot */
 
112
  pixmap = XCreatePixmap(dsp, win, width, height, DefaultDepth(dsp, scr));
 
113
 
 
114
  /* then copy the screen into the pixmap */
 
115
  gc = XCreateGC(dsp, pixmap, 0, NULL);
 
116
  XSetSubwindowMode(dsp, gc, IncludeInferiors);
 
117
  XCopyArea(dsp, root_win, pixmap, gc, aosd->x, aosd->y, width, height, 0, 0);
 
118
  XSetSubwindowMode(dsp, gc, ClipByChildren);
 
119
  XFreeGC(dsp, gc);
 
120
 
 
121
  return pixmap;
 
122
}
 
123
 
 
124
void
 
125
set_window_properties(Display* dsp, Window win)
 
126
{
 
127
  /* we're almost a _NET_WM_WINDOW_TYPE_SPLASH, but we don't want
 
128
   * to be centered on the screen.  instead, manually request the
 
129
   * behavior we want. */
 
130
 
 
131
  /* turn off window decorations.
 
132
   * we could pull this in from a motif header, but it's easier to
 
133
   * use this snippet i found on a mailing list. */
 
134
  Atom mwm_hints = XInternAtom(dsp, "_MOTIF_WM_HINTS", False);
 
135
  struct
 
136
  {
 
137
    long flags, functions, decorations, input_mode;
 
138
  }
 
139
  mwm_hints_setting = { (1L<<1), 0L, 0L, 0L };
 
140
 
 
141
  XChangeProperty(dsp, win, mwm_hints, mwm_hints, 32,
 
142
      PropModeReplace, (unsigned char *)&mwm_hints_setting, 4);
 
143
 
 
144
  /* always on top, not in taskbar or pager. */
 
145
  Atom win_state = XInternAtom(dsp, "_NET_WM_STATE", False);
 
146
  Atom win_state_setting[] =
 
147
  {
 
148
    XInternAtom(dsp, "_NET_WM_STATE_ABOVE", False),
 
149
    XInternAtom(dsp, "_NET_WM_STATE_SKIP_TASKBAR", False),
 
150
    XInternAtom(dsp, "_NET_WM_STATE_SKIP_PAGER", False)
 
151
  };
 
152
  XChangeProperty(dsp, win, win_state, XA_ATOM, 32,
 
153
      PropModeReplace, (unsigned char*)&win_state_setting, 3);
 
154
}
 
155
 
 
156
#ifdef HAVE_XCOMPOSITE
 
157
Bool
 
158
composite_check_ext_and_mgr(Display* dsp, int scr)
 
159
{
 
160
  int event_base, error_base;
 
161
  Atom comp_manager_atom;
 
162
  char comp_manager_hint[32];
 
163
  
 
164
  if (!XCompositeQueryExtension(dsp, &event_base, &error_base))
 
165
    return False;
 
166
 
 
167
  snprintf(comp_manager_hint, 32, "_NET_WM_CM_S%d", scr);
 
168
  comp_manager_atom = XInternAtom(dsp, comp_manager_hint, False);
 
169
 
 
170
  return (XGetSelectionOwner(dsp, comp_manager_atom) != None);
 
171
}
 
172
 
 
173
Visual*
 
174
composite_find_argb_visual(Display* dsp, int scr)
 
175
{
 
176
  XVisualInfo* xvi;
 
177
  XVisualInfo   template;
 
178
  int nvi, i;
 
179
  XRenderPictFormat* format;
 
180
  Visual* visual = NULL;
 
181
 
 
182
  template.screen = scr;
 
183
  template.depth = 32;
 
184
  template.class = TrueColor;
 
185
 
 
186
  xvi = XGetVisualInfo(dsp,
 
187
      VisualScreenMask | VisualDepthMask | VisualClassMask,
 
188
      &template, &nvi);
 
189
 
 
190
  if (xvi == NULL)
 
191
    return NULL;
 
192
 
 
193
  for (i = 0; i < nvi; i++)
 
194
  {
 
195
    format = XRenderFindVisualFormat(dsp, xvi[i].visual);
 
196
    if (format->type == PictTypeDirect &&
 
197
        format->direct.alphaMask)
 
198
    {
 
199
      visual = xvi[i].visual;
 
200
      break;
 
201
    }
 
202
  }
 
203
 
 
204
  XFree (xvi); 
 
205
  return visual;
 
206
}
 
207
#endif
 
208
 
 
209
/* vim: set ts=2 sw=2 et : */